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 3, 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 COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
28 with Hostparm
; use Hostparm
;
29 with Makeutl
; use Makeutl
;
30 with MLib
.Tgt
; use MLib
.Tgt
;
31 with Namet
; use Namet
;
32 with Output
; use Output
;
34 with Osint
; use Osint
;
36 with Prj
.Ext
; use Prj
.Ext
;
38 with Prj
.Util
; use Prj
.Util
;
39 with Snames
; use Snames
;
41 with Types
; use Types
;
43 with Ada
.Command_Line
; use Ada
.Command_Line
;
44 with Ada
.Strings
.Fixed
; use Ada
.Strings
.Fixed
;
45 with Ada
.Text_IO
; use Ada
.Text_IO
;
46 with Ada
.Unchecked_Deallocation
;
48 with GNAT
.Directory_Operations
; use GNAT
.Directory_Operations
;
49 with GNAT
.Dynamic_Tables
;
50 with GNAT
.Expect
; use GNAT
.Expect
;
52 with GNAT
.OS_Lib
; use GNAT
.OS_Lib
;
53 with GNAT
.Regpat
; use GNAT
.Regpat
;
56 with System
.Case_Util
; use System
.Case_Util
;
58 package body Makegpr
is
60 On_Windows
: constant Boolean := Directory_Separator
= '\';
61 -- True when on Windows. Used in Check_Compilation_Needed when processing
62 -- C/C++ dependency files for backslash handling.
64 Max_In_Archives
: constant := 50;
65 -- The maximum number of arguments for a single invocation of the
66 -- Archive Indexer (ar).
68 No_Argument
: aliased Argument_List
:= (1 .. 0 => null);
69 -- Null argument list representing case of no arguments
71 FD
: Process_Descriptor
;
72 -- The process descriptor used when invoking a non GNU compiler with -M
73 -- and getting the output with GNAT.Expect.
75 Line_Matcher
: constant Pattern_Matcher
:= Compile
("^.*?\n", Single_Line
);
76 -- Pattern for GNAT.Expect for the invocation of a non GNU compiler with -M
79 Name_Compiler_Command
: Name_Id
;
80 -- Names of package IDE and its attribute Compiler_Command.
81 -- Set up by Initialize.
83 Unique_Compile
: Boolean := False;
84 -- True when switch -u is used on the command line
86 type Source_Index_Rec
is record
89 Found
: Boolean := False;
91 -- Used as Source_Indexes component to check if archive needs to be rebuilt
93 type Source_Index_Array
is array (Positive range <>) of Source_Index_Rec
;
94 type Source_Indexes_Ref
is access Source_Index_Array
;
96 procedure Free
is new Ada
.Unchecked_Deallocation
97 (Source_Index_Array
, Source_Indexes_Ref
);
99 Initial_Source_Index_Count
: constant Positive := 20;
100 Source_Indexes
: Source_Indexes_Ref
:=
101 new Source_Index_Array
(1 .. Initial_Source_Index_Count
);
102 -- A list of the Other_Source_Ids of a project file, with an indication
103 -- that they have been found in the archive dependency file.
105 Last_Source
: Natural := 0;
106 -- The index of the last valid component of Source_Indexes
108 Compiler_Names
: array (First_Language_Indexes
) of String_Access
;
109 -- The names of the compilers to be used. Set up by Get_Compiler.
110 -- Used to display the commands spawned.
112 Gnatmake_String
: constant String_Access
:= new String'("gnatmake");
113 GCC_String : constant String_Access := new String'("gcc");
114 G_Plus_Plus_String
: constant String_Access
:= new String'("g++");
116 Default_Compiler_Names : constant array
117 (First_Language_Indexes range
118 Ada_Language_Index .. C_Plus_Plus_Language_Index)
120 (Ada_Language_Index => Gnatmake_String,
121 C_Language_Index => GCC_String,
122 C_Plus_Plus_Language_Index => G_Plus_Plus_String);
124 Compiler_Paths : array (First_Language_Indexes) of String_Access;
125 -- The path names of the compiler to be used. Set up by Get_Compiler.
126 -- Used to spawn compiling/linking processes.
128 Compiler_Is_Gcc : array (First_Language_Indexes) of Boolean;
129 -- An indication that a compiler is a GCC compiler, to be able to use
130 -- specific GCC switches.
132 Archive_Builder_Path : String_Access := null;
133 -- The path name of the archive builder (ar). To be used when spawning
136 Archive_Indexer_Path : String_Access := null;
137 -- The path name of the archive indexer (ranlib), if it exists
139 Copyright_Output : Boolean := False;
140 Usage_Output : Boolean := False;
141 -- Flags to avoid multiple displays of Copyright notice and of Usage
143 Output_File_Name : String_Access := null;
144 -- The name given after a switch -o
146 Output_File_Name_Expected : Boolean := False;
147 -- True when last switch was -o
149 Project_File_Name : String_Access := null;
150 -- The name of the project file specified with switch -P
152 Project_File_Name_Expected : Boolean := False;
153 -- True when last switch was -P
155 Naming_String : aliased String := "naming";
156 Builder_String : aliased String := "builder";
157 Compiler_String : aliased String := "compiler";
158 Binder_String : aliased String := "binder";
159 Linker_String : aliased String := "linker";
160 -- Name of packages to be checked when parsing/processing project files
162 List_Of_Packages : aliased String_List :=
163 (Naming_String 'Access,
164 Builder_String
'Access,
165 Compiler_String 'Access,
166 Binder_String
'Access,
167 Linker_String 'Access);
168 Packages_To_Check
: constant String_List_Access
:= List_Of_Packages
'Access;
169 -- List of the packages to be checked when parsing/processing project files
171 Project_Tree
: constant Project_Tree_Ref
:= new Project_Tree_Data
;
173 Main_Project
: Project_Id
;
174 -- The project id of the main project
176 type Processor
is (None
, Linker
, Compiler
);
177 Current_Processor
: Processor
:= None
;
178 -- This variable changes when switches -*args are used
180 Current_Language
: Language_Index
:= Ada_Language_Index
;
181 -- The compiler language to consider when Processor is Compiler
183 package Comp_Opts
is new GNAT
.Dynamic_Tables
184 (Table_Component_Type
=> String_Access
,
185 Table_Index_Type
=> Integer,
186 Table_Low_Bound
=> 1,
188 Table_Increment
=> 100);
189 Options
: array (First_Language_Indexes
) of Comp_Opts
.Instance
;
190 -- Tables to store compiling options for the different compilers
192 package Linker_Options
is new Table
.Table
193 (Table_Component_Type
=> String_Access
,
194 Table_Index_Type
=> Integer,
195 Table_Low_Bound
=> 1,
197 Table_Increment
=> 100,
198 Table_Name
=> "Makegpr.Linker_Options");
199 -- Table to store the linking options
201 package Library_Opts
is new Table
.Table
202 (Table_Component_Type
=> String_Access
,
203 Table_Index_Type
=> Integer,
204 Table_Low_Bound
=> 1,
206 Table_Increment
=> 100,
207 Table_Name
=> "Makegpr.Library_Opts");
208 -- Table to store the linking options
210 package Ada_Mains
is new Table
.Table
211 (Table_Component_Type
=> String_Access
,
212 Table_Index_Type
=> Integer,
213 Table_Low_Bound
=> 1,
215 Table_Increment
=> 100,
216 Table_Name
=> "Makegpr.Ada_Mains");
217 -- Table to store the Ada mains, either specified on the command line
218 -- or found in attribute Main of the main project file.
220 package Other_Mains
is new Table
.Table
221 (Table_Component_Type
=> Other_Source
,
222 Table_Index_Type
=> Integer,
223 Table_Low_Bound
=> 1,
225 Table_Increment
=> 100,
226 Table_Name
=> "Makegpr.Other_Mains");
227 -- Table to store the mains of languages other than Ada, either specified
228 -- on the command line or found in attribute Main of the main project file.
230 package Sources_Compiled
is new GNAT
.HTable
.Simple_HTable
231 (Header_Num
=> Header_Num
,
234 Key
=> File_Name_Type
,
238 package Saved_Switches
is new Table
.Table
239 (Table_Component_Type
=> String_Access
,
240 Table_Index_Type
=> Integer,
241 Table_Low_Bound
=> 1,
243 Table_Increment
=> 100,
244 Table_Name
=> "Makegpr.Saved_Switches");
245 -- Table to store the switches to be passed to gnatmake
247 Initial_Argument_Count
: constant Positive := 20;
248 type Boolean_Array
is array (Positive range <>) of Boolean;
249 type Booleans
is access Boolean_Array
;
251 procedure Free
is new Ada
.Unchecked_Deallocation
(Boolean_Array
, Booleans
);
253 Arguments
: Argument_List_Access
:=
254 new Argument_List
(1 .. Initial_Argument_Count
);
255 -- Used to store lists of arguments to be used when spawning a process
257 Arguments_Displayed
: Booleans
:=
258 new Boolean_Array
(1 .. Initial_Argument_Count
);
259 -- For each argument in Arguments, indicate if the argument should be
260 -- displayed when procedure Display_Command is called.
262 Last_Argument
: Natural := 0;
263 -- Index of the last valid argument in Arguments
265 package Cache_Args
is new Table
.Table
266 (Table_Component_Type
=> String_Access
,
267 Table_Index_Type
=> Integer,
268 Table_Low_Bound
=> 1,
269 Table_Initial
=> 200,
270 Table_Increment
=> 100,
271 Table_Name
=> "Makegpr.Cache_Args");
272 -- A table to cache arguments, to avoid multiple allocation of the same
273 -- strings. It is not possible to use a hash table, because String is
274 -- an unconstrained type.
276 -- Various switches used when spawning processes:
278 Dash_B_String
: aliased String := "-B";
279 Dash_B
: constant String_Access
:= Dash_B_String
'Access;
280 Dash_c_String
: aliased String := "-c";
281 Dash_c
: constant String_Access
:= Dash_c_String
'Access;
282 Dash_cargs_String
: aliased String := "-cargs";
283 Dash_cargs
: constant String_Access
:= Dash_cargs_String
'Access;
284 Dash_d_String
: aliased String := "-d";
285 Dash_d
: constant String_Access
:= Dash_d_String
'Access;
286 Dash_f_String
: aliased String := "-f";
287 Dash_f
: constant String_Access
:= Dash_f_String
'Access;
288 Dash_k_String
: aliased String := "-k";
289 Dash_k
: constant String_Access
:= Dash_k_String
'Access;
290 Dash_largs_String
: aliased String := "-largs";
291 Dash_largs
: constant String_Access
:= Dash_largs_String
'Access;
292 Dash_M_String
: aliased String := "-M";
293 Dash_M
: constant String_Access
:= Dash_M_String
'Access;
294 Dash_margs_String
: aliased String := "-margs";
295 Dash_margs
: constant String_Access
:= Dash_margs_String
'Access;
296 Dash_o_String
: aliased String := "-o";
297 Dash_o
: constant String_Access
:= Dash_o_String
'Access;
298 Dash_P_String
: aliased String := "-P";
299 Dash_P
: constant String_Access
:= Dash_P_String
'Access;
300 Dash_q_String
: aliased String := "-q";
301 Dash_q
: constant String_Access
:= Dash_q_String
'Access;
302 Dash_u_String
: aliased String := "-u";
303 Dash_u
: constant String_Access
:= Dash_u_String
'Access;
304 Dash_v_String
: aliased String := "-v";
305 Dash_v
: constant String_Access
:= Dash_v_String
'Access;
306 Dash_vP1_String
: aliased String := "-vP1";
307 Dash_vP1
: constant String_Access
:= Dash_vP1_String
'Access;
308 Dash_vP2_String
: aliased String := "-vP2";
309 Dash_vP2
: constant String_Access
:= Dash_vP2_String
'Access;
310 Dash_x_String
: aliased String := "-x";
311 Dash_x
: constant String_Access
:= Dash_x_String
'Access;
312 r_String
: aliased String := "r";
313 r
: constant String_Access
:= r_String
'Access;
315 CPATH
: constant String := "CPATH";
316 -- The environment variable to set when compiler is a GCC compiler
317 -- to indicate the include directory path.
319 Current_Include_Paths
: array (First_Language_Indexes
) of String_Access
;
320 -- A cache for the paths of included directories, to avoid setting
321 -- env var CPATH unnecessarily.
323 C_Plus_Plus_Is_Used
: Boolean := False;
324 -- True when there are sources in C++
326 Link_Options_Switches
: Argument_List_Access
:= null;
327 -- The link options coming from the attributes Linker'Linker_Options in
328 -- project files imported, directly or indirectly, by the main project.
330 Total_Number_Of_Errors
: Natural := 0;
331 -- Used when Keep_Going is True (switch -k) to keep the total number
332 -- of compilation/linking errors, to report at the end of execution.
334 Need_To_Rebuild_Global_Archive
: Boolean := False;
336 Error_Header
: constant String := "*** ERROR: ";
337 -- The beginning of error message, when Keep_Going is True
339 Need_To_Relink
: Boolean := False;
340 -- True when an executable of a language other than Ada need to be linked
342 Global_Archive_Exists
: Boolean := False;
343 -- True if there is a non empty global archive, to prevent creation
346 Path_Option
: String_Access
;
347 -- The path option switch, when supported
349 Project_Of_Current_Object_Directory
: Project_Id
:= No_Project
;
350 -- The object directory of the project for the last compilation. Avoid
351 -- calling Change_Dir if the current working directory is already this
354 package Lib_Path
is new Table
.Table
355 (Table_Component_Type
=> Character,
356 Table_Index_Type
=> Integer,
357 Table_Low_Bound
=> 1,
358 Table_Initial
=> 200,
359 Table_Increment
=> 100,
360 Table_Name
=> "Makegpr.Lib_Path");
361 -- A table to compute the path to put in the path option switch, when it
364 procedure Add_Archives
(For_Gnatmake
: Boolean);
365 -- Add to Arguments the list of archives for linking an executable
367 procedure Add_Argument
(Arg
: String_Access
; Display
: Boolean);
368 procedure Add_Argument
(Arg
: String; Display
: Boolean);
369 -- Add an argument to Arguments. Reallocate if necessary
371 procedure Add_Arguments
(Args
: Argument_List
; Display
: Boolean);
372 -- Add a list of arguments to Arguments. Reallocate if necessary
374 procedure Add_Option
(Arg
: String);
375 -- Add a switch for the Ada, C or C++ compiler, or for the linker.
376 -- The table where this option is stored depends on the values of
377 -- Current_Processor and Current_Language.
379 procedure Add_Search_Directories
380 (Data
: Project_Data
;
381 Language
: First_Language_Indexes
);
382 -- Either add to the Arguments the necessary -I switches needed to
383 -- compile, or, when compiler is gcc/g++, set up the C*INCLUDE_PATH
384 -- environment variable, if necessary.
386 procedure Add_Source_Id
(Project
: Project_Id
; Id
: Other_Source_Id
);
387 -- Add a source id to Source_Indexes, with Found set to False
389 procedure Add_Switches
390 (Data
: Project_Data
;
392 Language
: Language_Index
;
393 File_Name
: File_Name_Type
);
394 -- Add to Arguments the switches, if any, for a source (attribute Switches)
395 -- or language (attribute Default_Switches), coming from package Compiler
396 -- or Linker (depending on Proc) of a specified project file.
398 procedure Build_Global_Archive
;
399 -- Build the archive for the main project
401 procedure Build_Library
(Project
: Project_Id
; Unconditionally
: Boolean);
402 -- Build the library for a library project. If Unconditionally is
403 -- False, first check if the library is up to date, and build it only
406 procedure Check
(Option
: String);
407 -- Check that a switch coming from a project file is not the concatenation
408 -- of several valid switch, for example "-g -v". If it is, issue a warning.
410 procedure Check_Archive_Builder
;
411 -- Check if the archive builder (ar) is there
413 procedure Check_Compilation_Needed
414 (Source
: Other_Source
;
415 Need_To_Compile
: out Boolean);
416 -- Check if a source of a language other than Ada needs to be compiled or
419 procedure Check_For_C_Plus_Plus
;
420 -- Check if C++ is used in at least one project
423 (Source_Id
: Other_Source_Id
;
425 Local_Errors
: in out Boolean);
426 -- Compile one non-Ada source
428 procedure Compile_Individual_Sources
;
429 -- Compile the sources specified on the command line, when in
430 -- Unique_Compile mode.
432 procedure Compile_Link_With_Gnatmake
(Mains_Specified
: Boolean);
433 -- Compile/Link with gnatmake when there are Ada sources in the main
434 -- project. Arguments may already contain options to be used by
435 -- gnatmake. Used for both Ada mains and mains of other languages.
436 -- When Compile_Only is True, do not use the linking options
438 procedure Compile_Sources
;
439 -- Compile the sources of languages other than Ada, if necessary
442 -- Output the Copyright notice
444 procedure Create_Archive_Dependency_File
446 First_Source
: Other_Source_Id
);
447 -- Create the archive dependency file for a library project
449 procedure Create_Global_Archive_Dependency_File
(Name
: String);
450 -- Create the archive depenency file for the main project
452 procedure Display_Command
454 Path
: String_Access
;
455 CPATH
: String_Access
:= null;
456 Ellipse
: Boolean := False);
457 -- Display the command for a spawned process, if in Verbose_Mode or not in
458 -- Quiet_Output. In non verbose mode, when Ellipse is True, display "..."
459 -- in place of the first argument that has Display set to False.
461 procedure Get_Compiler
(For_Language
: First_Language_Indexes
);
462 -- Find the compiler name and path name for a specified programming
463 -- language, if not already done. Results are in the corresponding elements
464 -- of arrays Compiler_Names and Compiler_Paths. Name of compiler is found
465 -- in package IDE of the main project, or defaulted. Fail if compiler
466 -- cannot be found on the path. For the Ada language, gnatmake, rather than
467 -- the Ada compiler is returned.
469 procedure Get_Imported_Directories
470 (Project
: Project_Id
;
471 Data
: in out Project_Data
);
472 -- Find the necessary switches -I to be used when compiling sources of
473 -- languages other than Ada, in a specified project file. Cache the result
474 -- in component Imported_Directories_Switches of the project data. For
475 -- gcc/g++ compilers, get the value of the C*_INCLUDE_PATH, instead.
477 procedure Initialize
;
478 -- Do the necessary package initialization and process the command line
481 function Is_Included_In_Global_Archive
482 (Object_Name
: File_Name_Type
;
483 Project
: Project_Id
) return Boolean;
484 -- Return True if the object Object_Name is not overridden by a source
485 -- in a project extending project Project.
487 procedure Link_Executables
;
490 procedure Report_Error
(S1
: String; S2
: String := ""; S3
: String := "");
491 -- Report an error. If Keep_Going is False, just call Osint.Fail. If
492 -- Keep_Going is True, display the error and increase the total number of
495 procedure Report_Total_Errors
(Kind
: String);
496 -- If Total_Number_Of_Errors is not zero, report it, and fail
498 procedure Scan_Arg
(Arg
: String);
499 -- Process one command line argument
501 function Strip_CR_LF
(Text
: String) return String;
502 -- Remove characters ASCII.CR and ASCII.LF from a String
511 procedure Add_Archives
(For_Gnatmake
: Boolean) is
512 Last_Arg
: constant Natural := Last_Argument
;
513 -- The position of the last argument before adding the archives. Used to
514 -- reverse the order of the arguments added when processing the
517 procedure Recursive_Add_Archives
(Project
: Project_Id
);
518 -- Recursive procedure to add the archive of a project file, if any,
519 -- then call itself for the project imported.
521 ----------------------------
522 -- Recursive_Add_Archives --
523 ----------------------------
525 procedure Recursive_Add_Archives
(Project
: Project_Id
) is
527 Imported
: Project_List
;
530 procedure Add_Archive_Path
;
531 -- For a library project or the main project, add the archive
532 -- path to the arguments.
534 ----------------------
535 -- Add_Archive_Path --
536 ----------------------
538 procedure Add_Archive_Path
is
539 Increment
: Positive;
540 Prev_Last
: Positive;
545 -- If it is a library project file, nothing to do if gnatmake
546 -- will be invoked, because gnatmake will take care of it, even
547 -- if the library is not an Ada library.
549 if not For_Gnatmake
then
550 if Data
.Library_Kind
= Static
then
552 (Get_Name_String
(Data
.Display_Library_Dir
) &
553 Directory_Separator
&
554 "lib" & Get_Name_String
(Data
.Library_Name
) &
559 -- As we first insert in the reverse order,
560 -- -L<dir> is put after -l<lib>
563 ("-l" & Get_Name_String
(Data
.Library_Name
),
566 Get_Name_String
(Data
.Display_Library_Dir
);
569 ("-L" & Name_Buffer
(1 .. Name_Len
),
572 -- If there is a run path option, prepend this directory
573 -- to the library path. It is probable that the order of
574 -- the directories in the path option is not important,
575 -- but just in case put the directories in the same order
578 if Path_Option
/= null then
580 -- If it is not the first directory, make room at the
581 -- beginning of the table, including for a path
584 if Lib_Path
.Last
> 0 then
585 Increment
:= Name_Len
+ 1;
586 Prev_Last
:= Lib_Path
.Last
;
587 Lib_Path
.Set_Last
(Prev_Last
+ Increment
);
589 for Index
in reverse 1 .. Prev_Last
loop
590 Lib_Path
.Table
(Index
+ Increment
) :=
591 Lib_Path
.Table
(Index
);
594 Lib_Path
.Table
(Increment
) := Path_Separator
;
597 -- If it is the first directory, just set
598 -- Last to the length of the directory.
600 Lib_Path
.Set_Last
(Name_Len
);
603 -- Put the directory at the beginning of the
606 for Index
in 1 .. Name_Len
loop
607 Lib_Path
.Table
(Index
) := Name_Buffer
(Index
);
613 -- For a non-library project, the only archive needed is the one
614 -- for the main project, if there is one.
616 elsif Project
= Main_Project
and then Global_Archive_Exists
then
618 (Get_Name_String
(Data
.Display_Object_Dir
) &
619 Directory_Separator
&
620 "lib" & Get_Name_String
(Data
.Display_Name
)
624 end Add_Archive_Path
;
627 -- Nothing to do when there is no project specified
629 if Project
/= No_Project
then
630 Data
:= Project_Tree
.Projects
.Table
(Project
);
632 -- Nothing to do if the project has already been processed
634 if not Data
.Seen
then
636 -- Mark the project as processed, to avoid processing it again
638 Project_Tree
.Projects
.Table
(Project
).Seen
:= True;
640 Recursive_Add_Archives
(Data
.Extends
);
642 Imported
:= Data
.Imported_Projects
;
644 -- Call itself recursively for all imported projects
646 while Imported
/= Empty_Project_List
loop
647 Prj
:= Project_Tree
.Project_Lists
.Table
650 if Prj
/= No_Project
then
651 while Project_Tree
.Projects
.Table
652 (Prj
).Extended_By
/= No_Project
654 Prj
:= Project_Tree
.Projects
.Table
658 Recursive_Add_Archives
(Prj
);
661 Imported
:= Project_Tree
.Project_Lists
.Table
665 -- If there is sources of language other than Ada in this
666 -- project, add the path of the archive to Arguments.
668 if Project
= Main_Project
669 or else Data
.Other_Sources_Present
675 end Recursive_Add_Archives
;
677 -- Start of processing for Add_Archives
680 -- First, mark all projects as not processed
682 for Project
in Project_Table
.First
..
683 Project_Table
.Last
(Project_Tree
.Projects
)
685 Project_Tree
.Projects
.Table
(Project
).Seen
:= False;
688 -- Take care of the run path option
690 if Path_Option
= null then
691 Path_Option
:= MLib
.Linker_Library_Path_Option
;
694 Lib_Path
.Set_Last
(0);
696 -- Add archives in the reverse order
698 Recursive_Add_Archives
(Main_Project
);
700 -- And reverse the order
705 Temp
: String_Access
;
708 First
:= Last_Arg
+ 1;
709 Last
:= Last_Argument
;
710 while First
< Last
loop
711 Temp
:= Arguments
(First
);
712 Arguments
(First
) := Arguments
(Last
);
713 Arguments
(Last
) := Temp
;
724 procedure Add_Argument
(Arg
: String_Access
; Display
: Boolean) is
726 -- Nothing to do if no argument is specified or if argument is empty
728 if Arg
/= null or else Arg
'Length = 0 then
730 -- Reallocate arrays if necessary
732 if Last_Argument
= Arguments
'Last then
734 New_Arguments
: constant Argument_List_Access
:=
736 (1 .. Last_Argument
+
737 Initial_Argument_Count
);
739 New_Arguments_Displayed
: constant Booleans
:=
741 (1 .. Last_Argument
+
742 Initial_Argument_Count
);
745 New_Arguments
(Arguments
'Range) := Arguments
.all;
747 -- To avoid deallocating the strings, nullify all components
748 -- of Arguments before calling Free.
750 Arguments
.all := (others => null);
753 Arguments
:= New_Arguments
;
755 New_Arguments_Displayed
(Arguments_Displayed
'Range) :=
756 Arguments_Displayed
.all;
757 Free
(Arguments_Displayed
);
758 Arguments_Displayed
:= New_Arguments_Displayed
;
762 -- Add the argument and its display indication
764 Last_Argument
:= Last_Argument
+ 1;
765 Arguments
(Last_Argument
) := Arg
;
766 Arguments_Displayed
(Last_Argument
) := Display
;
770 procedure Add_Argument
(Arg
: String; Display
: Boolean) is
771 Argument
: String_Access
:= null;
774 -- Nothing to do if argument is empty
776 if Arg
'Length > 0 then
778 -- Check if the argument is already in the Cache_Args table.
779 -- If it is already there, reuse the allocated value.
781 for Index
in 1 .. Cache_Args
.Last
loop
782 if Cache_Args
.Table
(Index
).all = Arg
then
783 Argument
:= Cache_Args
.Table
(Index
);
788 -- If the argument is not in the cache, create a new entry in the
791 if Argument
= null then
792 Argument
:= new String'(Arg);
793 Cache_Args.Increment_Last;
794 Cache_Args.Table (Cache_Args.Last) := Argument;
797 -- And add the argument
799 Add_Argument (Argument, Display);
807 procedure Add_Arguments (Args : Argument_List; Display : Boolean) is
809 -- Reallocate the arrays, if necessary
811 if Last_Argument + Args'Length > Arguments'Last then
813 New_Arguments : constant Argument_List_Access :=
815 (1 .. Last_Argument + Args'Length +
816 Initial_Argument_Count);
818 New_Arguments_Displayed : constant Booleans :=
820 (1 .. Last_Argument +
822 Initial_Argument_Count);
825 New_Arguments (1 .. Last_Argument) :=
826 Arguments (1 .. Last_Argument);
828 -- To avoid deallocating the strings, nullify all components
829 -- of Arguments before calling Free.
831 Arguments.all := (others => null);
834 Arguments := New_Arguments;
835 New_Arguments_Displayed (1 .. Last_Argument) :=
836 Arguments_Displayed (1 .. Last_Argument);
837 Free (Arguments_Displayed);
838 Arguments_Displayed := New_Arguments_Displayed;
842 -- Add the new arguments and the display indications
844 Arguments (Last_Argument + 1 .. Last_Argument + Args'Length) := Args;
845 Arguments_Displayed (Last_Argument + 1 .. Last_Argument + Args'Length) :=
847 Last_Argument := Last_Argument + Args'Length;
854 procedure Add_Option (Arg : String) is
855 Option : constant String_Access := new String'(Arg
);
858 case Current_Processor
is
864 -- Add option to the linker table
866 Linker_Options
.Increment_Last
;
867 Linker_Options
.Table
(Linker_Options
.Last
) := Option
;
871 -- Add option to the compiler option table, depending on the
872 -- value of Current_Language.
874 Comp_Opts
.Increment_Last
(Options
(Current_Language
));
875 Options
(Current_Language
).Table
876 (Comp_Opts
.Last
(Options
(Current_Language
))) := Option
;
885 procedure Add_Source_Id
(Project
: Project_Id
; Id
: Other_Source_Id
) is
887 -- Reallocate the array, if necessary
889 if Last_Source
= Source_Indexes
'Last then
891 New_Indexes
: constant Source_Indexes_Ref
:=
892 new Source_Index_Array
893 (1 .. Source_Indexes
'Last +
894 Initial_Source_Index_Count
);
896 New_Indexes
(Source_Indexes
'Range) := Source_Indexes
.all;
897 Free
(Source_Indexes
);
898 Source_Indexes
:= New_Indexes
;
902 Last_Source
:= Last_Source
+ 1;
903 Source_Indexes
(Last_Source
) := (Project
, Id
, False);
906 ----------------------------
907 -- Add_Search_Directories --
908 ----------------------------
910 procedure Add_Search_Directories
911 (Data
: Project_Data
;
912 Language
: First_Language_Indexes
)
915 -- If a GNU compiler is used, set the CPATH environment variable,
916 -- if it does not already has the correct value.
918 if Compiler_Is_Gcc
(Language
) then
919 if Current_Include_Paths
(Language
) /= Data
.Include_Path
then
920 Current_Include_Paths
(Language
) := Data
.Include_Path
;
921 Setenv
(CPATH
, Data
.Include_Path
.all);
925 Add_Arguments
(Data
.Imported_Directories_Switches
.all, Verbose_Mode
);
927 end Add_Search_Directories
;
933 procedure Add_Switches
934 (Data
: Project_Data
;
936 Language
: Language_Index
;
937 File_Name
: File_Name_Type
)
939 Switches
: Variable_Value
;
940 -- The switches, if any, for the file/language
943 -- The id of the package where to look for the switches
945 Defaults
: Array_Element_Id
;
946 -- The Default_Switches associative array
948 Switches_Array
: Array_Element_Id
;
949 -- The Switches associative array
951 Element_Id
: String_List_Id
;
952 Element
: String_Element
;
955 -- First, choose the proper package
962 Pkg
:= Value_Of
(Name_Linker
, Data
.Decl
.Packages
, Project_Tree
);
965 Pkg
:= Value_Of
(Name_Compiler
, Data
.Decl
.Packages
, Project_Tree
);
968 if Pkg
/= No_Package
then
970 -- Get the Switches ("file name"), if they exist
972 Switches_Array
:= Prj
.Util
.Value_Of
973 (Name
=> Name_Switches
,
974 In_Arrays
=> Project_Tree
.Packages
.Table
976 In_Tree
=> Project_Tree
);
980 (Index
=> Name_Id
(File_Name
),
982 In_Array
=> Switches_Array
,
983 In_Tree
=> Project_Tree
);
985 -- Otherwise, get the Default_Switches ("language"), if they exist
987 if Switches
= Nil_Variable_Value
then
988 Defaults
:= Prj
.Util
.Value_Of
989 (Name
=> Name_Default_Switches
,
990 In_Arrays
=> Project_Tree
.Packages
.Table
992 In_Tree
=> Project_Tree
);
993 Switches
:= Prj
.Util
.Value_Of
994 (Index
=> Language_Names
.Table
(Language
),
996 In_Array
=> Defaults
,
997 In_Tree
=> Project_Tree
);
1000 -- If there are switches, add them to Arguments
1002 if Switches
/= Nil_Variable_Value
then
1003 Element_Id
:= Switches
.Values
;
1004 while Element_Id
/= Nil_String
loop
1005 Element
:= Project_Tree
.String_Elements
.Table
1008 if Element
.Value
/= No_Name
then
1009 Get_Name_String
(Element
.Value
);
1011 if not Quiet_Output
then
1013 -- When not in quiet output (no -q), check that the
1014 -- switch is not the concatenation of several valid
1015 -- switches, such as "-g -v". If it is, issue a warning.
1017 Check
(Option
=> Name_Buffer
(1 .. Name_Len
));
1020 Add_Argument
(Name_Buffer
(1 .. Name_Len
), True);
1023 Element_Id
:= Element
.Next
;
1029 --------------------------
1030 -- Build_Global_Archive --
1031 --------------------------
1033 procedure Build_Global_Archive
is
1034 Data
: Project_Data
:= Project_Tree
.Projects
.Table
(Main_Project
);
1035 Source_Id
: Other_Source_Id
;
1036 S_Id
: Other_Source_Id
;
1037 Source
: Other_Source
;
1040 Archive_Name
: constant String :=
1042 & Get_Name_String
(Data
.Display_Name
)
1045 -- The name of the archive file for this project
1047 Archive_Dep_Name
: constant String :=
1049 & Get_Name_String
(Data
.Display_Name
)
1051 -- The name of the archive dependency file for this project
1053 Need_To_Rebuild
: Boolean := Need_To_Rebuild_Global_Archive
;
1054 -- When True, archive will be rebuilt
1056 File
: Prj
.Util
.Text_File
;
1057 Object_Path
: Path_Name_Type
;
1058 Time_Stamp
: Time_Stamp_Type
;
1059 Saved_Last_Argument
: Natural;
1060 First_Object
: Natural;
1063 pragma Warnings
(Off
, Discard
);
1066 Check_Archive_Builder
;
1068 if Project_Of_Current_Object_Directory
/= Main_Project
then
1069 Project_Of_Current_Object_Directory
:= Main_Project
;
1070 Change_Dir
(Get_Name_String
(Data
.Object_Directory
));
1072 if Verbose_Mode
then
1073 Write_Str
("Changing to object directory of """);
1074 Write_Name
(Data
.Display_Name
);
1075 Write_Str
(""": """);
1076 Write_Name
(Data
.Display_Object_Dir
);
1081 if not Need_To_Rebuild
then
1082 if Verbose_Mode
then
1083 Write_Str
(" Checking ");
1084 Write_Line
(Archive_Name
);
1087 -- If the archive does not exist, of course it needs to be built
1089 if not Is_Regular_File
(Archive_Name
) then
1090 Need_To_Rebuild
:= True;
1092 if Verbose_Mode
then
1093 Write_Line
(" -> archive does not exist");
1096 -- Archive does exist
1099 -- Check the archive dependency file
1101 Open
(File
, Archive_Dep_Name
);
1103 -- If the archive dependency file does not exist, we need to
1104 -- rebuild the archive and to create its dependency file.
1106 if not Is_Valid
(File
) then
1107 Need_To_Rebuild
:= True;
1109 if Verbose_Mode
then
1110 Write_Str
(" -> archive dependency file ");
1111 Write_Str
(Archive_Dep_Name
);
1112 Write_Line
(" does not exist");
1116 -- Put all sources of language other than Ada in Source_Indexes
1119 Local_Data
: Project_Data
;
1124 for Proj
in Project_Table
.First
..
1125 Project_Table
.Last
(Project_Tree
.Projects
)
1127 Local_Data
:= Project_Tree
.Projects
.Table
(Proj
);
1129 if not Local_Data
.Library
then
1130 Source_Id
:= Local_Data
.First_Other_Source
;
1131 while Source_Id
/= No_Other_Source
loop
1132 Add_Source_Id
(Proj
, Source_Id
);
1133 Source_Id
:= Project_Tree
.Other_Sources
.Table
1140 -- Read the dependency file, line by line
1142 while not End_Of_File
(File
) loop
1143 Get_Line
(File
, Name_Buffer
, Name_Len
);
1145 -- First line is the path of the object file
1147 Object_Path
:= Name_Find
;
1148 Source_Id
:= No_Other_Source
;
1150 -- Check if this object file is for a source of this project
1152 for S
in 1 .. Last_Source
loop
1153 S_Id
:= Source_Indexes
(S
).Id
;
1154 Source
:= Project_Tree
.Other_Sources
.Table
(S_Id
);
1156 if (not Source_Indexes
(S
).Found
)
1157 and then Source
.Object_Path
= Object_Path
1159 -- We have found the object file: get the source data,
1160 -- and mark it as found.
1163 Source_Indexes
(S
).Found
:= True;
1168 -- If it is not for a source of this project, then the
1169 -- archive needs to be rebuilt.
1171 if Source_Id
= No_Other_Source
then
1172 Need_To_Rebuild
:= True;
1173 if Verbose_Mode
then
1175 Write_Str
(Get_Name_String
(Object_Path
));
1176 Write_Line
(" is not an object of any project");
1182 -- The second line is the time stamp of the object file. If
1183 -- there is no next line, then the dependency file is
1184 -- truncated, and the archive need to be rebuilt.
1186 if End_Of_File
(File
) then
1187 Need_To_Rebuild
:= True;
1189 if Verbose_Mode
then
1190 Write_Str
(" -> archive dependency file ");
1191 Write_Line
(" is truncated");
1197 Get_Line
(File
, Name_Buffer
, Name_Len
);
1199 -- If the line has the wrong number of characters, then
1200 -- the dependency file is incorrectly formatted, and the
1201 -- archive needs to be rebuilt.
1203 if Name_Len
/= Time_Stamp_Length
then
1204 Need_To_Rebuild
:= True;
1206 if Verbose_Mode
then
1207 Write_Str
(" -> archive dependency file ");
1208 Write_Line
(" is incorrectly formatted (time stamp)");
1214 Time_Stamp
:= Time_Stamp_Type
(Name_Buffer
(1 .. Name_Len
));
1216 -- If the time stamp in the dependency file is different
1217 -- from the time stamp of the object file, then the archive
1218 -- needs to be rebuilt.
1220 if Time_Stamp
/= Source
.Object_TS
then
1221 Need_To_Rebuild
:= True;
1223 if Verbose_Mode
then
1224 Write_Str
(" -> time stamp of ");
1225 Write_Str
(Get_Name_String
(Object_Path
));
1226 Write_Str
(" is incorrect in the archive");
1227 Write_Line
(" dependency file");
1239 if not Need_To_Rebuild
then
1240 if Verbose_Mode
then
1241 Write_Line
(" -> up to date");
1244 -- No need to create a global archive, if there is no object
1245 -- file to put into.
1247 Global_Archive_Exists
:= Last_Source
/= 0;
1249 -- Archive needs to be rebuilt
1252 -- If archive already exists, first delete it
1254 -- Comment needed on why we discard result???
1256 if Is_Regular_File
(Archive_Name
) then
1257 Delete_File
(Archive_Name
, Discard
);
1262 -- Start with the options found in MLib.Tgt (usually just "rc")
1264 Add_Arguments
(Archive_Builder_Options
.all, True);
1266 -- Followed by the archive name
1268 Add_Argument
(Archive_Name
, True);
1270 First_Object
:= Last_Argument
;
1272 -- Followed by all the object files of the non library projects
1274 for Proj
in Project_Table
.First
..
1275 Project_Table
.Last
(Project_Tree
.Projects
)
1277 Data
:= Project_Tree
.Projects
.Table
(Proj
);
1279 if not Data
.Library
then
1280 Source_Id
:= Data
.First_Other_Source
;
1281 while Source_Id
/= No_Other_Source
loop
1283 Project_Tree
.Other_Sources
.Table
(Source_Id
);
1285 -- Only include object file name that have not been
1286 -- overriden in extending projects.
1288 if Is_Included_In_Global_Archive
1289 (Source
.Object_Name
, Proj
)
1292 (Get_Name_String
(Source
.Object_Path
),
1293 Verbose_Mode
or (First_Object
= Last_Argument
));
1296 Source_Id
:= Source
.Next
;
1301 -- No need to create a global archive, if there is no object
1302 -- file to put into.
1304 Global_Archive_Exists
:= Last_Argument
> First_Object
;
1306 if Global_Archive_Exists
then
1308 -- If the archive is built, then linking will need to occur
1311 Need_To_Relink
:= True;
1313 -- Spawn the archive builder (ar)
1315 Saved_Last_Argument
:= Last_Argument
;
1316 Last_Argument
:= First_Object
+ Max_In_Archives
;
1318 if Last_Argument
> Saved_Last_Argument
then
1319 Last_Argument
:= Saved_Last_Argument
;
1324 Archive_Builder_Path
,
1328 (Archive_Builder_Path
.all,
1329 Arguments
(1 .. Last_Argument
),
1332 exit when not Success
1333 or else Last_Argument
= Saved_Last_Argument
;
1336 Arguments
(3 .. Saved_Last_Argument
- Last_Argument
+ 2) :=
1337 Arguments
(Last_Argument
+ 1 .. Saved_Last_Argument
);
1338 Saved_Last_Argument
:= Saved_Last_Argument
- Last_Argument
+ 2;
1341 -- If the archive was built, run the archive indexer (ranlib)
1346 if Archive_Indexer_Path
/= null then
1348 Add_Argument
(Archive_Name
, True);
1350 Display_Command
(Archive_Indexer
, Archive_Indexer_Path
);
1353 (Archive_Indexer_Path
.all, Arguments
(1 .. 1), Success
);
1357 -- Running ranlib failed, delete the dependency file,
1360 if Is_Regular_File
(Archive_Dep_Name
) then
1361 Delete_File
(Archive_Dep_Name
, Success
);
1364 -- And report the error
1367 ("running" & Archive_Indexer
& " for project """,
1368 Get_Name_String
(Data
.Display_Name
),
1374 -- The archive was correctly built, create its dependency file
1376 Create_Global_Archive_Dependency_File
(Archive_Dep_Name
);
1378 -- Building the archive failed, delete dependency file if one
1382 if Is_Regular_File
(Archive_Dep_Name
) then
1383 Delete_File
(Archive_Dep_Name
, Success
);
1386 -- And report the error
1389 ("building archive for project """,
1390 Get_Name_String
(Data
.Display_Name
),
1395 end Build_Global_Archive
;
1401 procedure Build_Library
(Project
: Project_Id
; Unconditionally
: Boolean) is
1402 Data
: constant Project_Data
:=
1403 Project_Tree
.Projects
.Table
(Project
);
1404 Source_Id
: Other_Source_Id
;
1405 Source
: Other_Source
;
1407 Archive_Name
: constant String :=
1408 "lib" & Get_Name_String
(Data
.Library_Name
)
1409 & '.' & Archive_Ext
;
1410 -- The name of the archive file for this project
1412 Archive_Dep_Name
: constant String :=
1413 "lib" & Get_Name_String
(Data
.Library_Name
)
1415 -- The name of the archive dependency file for this project
1417 Need_To_Rebuild
: Boolean := Unconditionally
;
1418 -- When True, archive will be rebuilt
1420 File
: Prj
.Util
.Text_File
;
1422 Object_Name
: File_Name_Type
;
1423 Time_Stamp
: Time_Stamp_Type
;
1424 Driver_Name
: Name_Id
:= No_Name
;
1426 Lib_Opts
: Argument_List_Access
:= No_Argument
'Access;
1429 -- Nothing to do if the project is externally built
1431 if Data
.Externally_Built
then
1435 Check_Archive_Builder
;
1437 -- If Unconditionally is False, check if the archive need to be built
1439 if not Need_To_Rebuild
then
1440 if Verbose_Mode
then
1441 Write_Str
(" Checking ");
1442 Write_Line
(Archive_Name
);
1445 -- If the archive does not exist, of course it needs to be built
1447 if not Is_Regular_File
(Archive_Name
) then
1448 Need_To_Rebuild
:= True;
1450 if Verbose_Mode
then
1451 Write_Line
(" -> archive does not exist");
1454 -- Archive does exist
1457 -- Check the archive dependency file
1459 Open
(File
, Archive_Dep_Name
);
1461 -- If the archive dependency file does not exist, we need to
1462 -- rebuild the archive and to create its dependency file.
1464 if not Is_Valid
(File
) then
1465 Need_To_Rebuild
:= True;
1467 if Verbose_Mode
then
1468 Write_Str
(" -> archive dependency file ");
1469 Write_Str
(Archive_Dep_Name
);
1470 Write_Line
(" does not exist");
1474 -- Put all sources of language other than Ada in Source_Indexes
1478 Source_Id
:= Data
.First_Other_Source
;
1479 while Source_Id
/= No_Other_Source
loop
1480 Add_Source_Id
(Project
, Source_Id
);
1482 Project_Tree
.Other_Sources
.Table
(Source_Id
).Next
;
1485 -- Read the dependency file, line by line
1487 while not End_Of_File
(File
) loop
1488 Get_Line
(File
, Name_Buffer
, Name_Len
);
1490 -- First line is the name of an object file
1492 Object_Name
:= Name_Find
;
1493 Source_Id
:= No_Other_Source
;
1495 -- Check if this object file is for a source of this project
1497 for S
in 1 .. Last_Source
loop
1498 if (not Source_Indexes
(S
).Found
)
1500 Project_Tree
.Other_Sources
.Table
1501 (Source_Indexes
(S
).Id
).Object_Name
= Object_Name
1503 -- We have found the object file: get the source
1504 -- data, and mark it as found.
1506 Source_Id
:= Source_Indexes
(S
).Id
;
1507 Source
:= Project_Tree
.Other_Sources
.Table
1509 Source_Indexes
(S
).Found
:= True;
1514 -- If it is not for a source of this project, then the
1515 -- archive needs to be rebuilt.
1517 if Source_Id
= No_Other_Source
then
1518 Need_To_Rebuild
:= True;
1520 if Verbose_Mode
then
1522 Write_Str
(Get_Name_String
(Object_Name
));
1523 Write_Line
(" is not an object of the project");
1529 -- The second line is the time stamp of the object file.
1530 -- If there is no next line, then the dependency file is
1531 -- truncated, and the archive need to be rebuilt.
1533 if End_Of_File
(File
) then
1534 Need_To_Rebuild
:= True;
1536 if Verbose_Mode
then
1537 Write_Str
(" -> archive dependency file ");
1538 Write_Line
(" is truncated");
1544 Get_Line
(File
, Name_Buffer
, Name_Len
);
1546 -- If the line has the wrong number of character, then
1547 -- the dependency file is incorrectly formatted, and the
1548 -- archive needs to be rebuilt.
1550 if Name_Len
/= Time_Stamp_Length
then
1551 Need_To_Rebuild
:= True;
1553 if Verbose_Mode
then
1554 Write_Str
(" -> archive dependency file ");
1555 Write_Line
(" is incorrectly formatted (time stamp)");
1561 Time_Stamp
:= Time_Stamp_Type
(Name_Buffer
(1 .. Name_Len
));
1563 -- If the time stamp in the dependency file is different
1564 -- from the time stamp of the object file, then the archive
1565 -- needs to be rebuilt.
1567 if Time_Stamp
/= Source
.Object_TS
then
1568 Need_To_Rebuild
:= True;
1570 if Verbose_Mode
then
1571 Write_Str
(" -> time stamp of ");
1572 Write_Str
(Get_Name_String
(Object_Name
));
1573 Write_Str
(" is incorrect in the archive");
1574 Write_Line
(" dependency file");
1583 if not Need_To_Rebuild
then
1585 -- Now, check if all object files of the project have been
1586 -- accounted for. If any of them is not in the dependency
1587 -- file, the archive needs to be rebuilt.
1589 for Index
in 1 .. Last_Source
loop
1590 if not Source_Indexes
(Index
).Found
then
1591 Need_To_Rebuild
:= True;
1593 if Verbose_Mode
then
1594 Source_Id
:= Source_Indexes
(Index
).Id
;
1595 Source
:= Project_Tree
.Other_Sources
.Table
1598 Write_Str
(Get_Name_String
(Source
.Object_Name
));
1599 Write_Str
(" is not in the archive ");
1600 Write_Line
("dependency file");
1608 if (not Need_To_Rebuild
) and Verbose_Mode
then
1609 Write_Line
(" -> up to date");
1615 -- Build the library if necessary
1617 if Need_To_Rebuild
then
1619 -- If a library is built, then linking will need to occur
1622 Need_To_Relink
:= True;
1626 -- If there are sources in Ada, then gnatmake will build the library,
1627 -- so nothing to do.
1629 if not Data
.Langs
(Ada_Language_Index
) then
1631 -- Get all the object files of the project
1633 Source_Id
:= Data
.First_Other_Source
;
1634 while Source_Id
/= No_Other_Source
loop
1635 Source
:= Project_Tree
.Other_Sources
.Table
(Source_Id
);
1637 (Get_Name_String
(Source
.Object_Name
), Verbose_Mode
);
1638 Source_Id
:= Source
.Next
;
1641 -- If it is a library, it need to be built it the same way Ada
1642 -- libraries are built.
1644 if Data
.Library_Kind
= Static
then
1646 (Ofiles
=> Arguments
(1 .. Last_Argument
),
1647 Output_File
=> Get_Name_String
(Data
.Library_Name
),
1648 Output_Dir
=> Get_Name_String
(Data
.Display_Library_Dir
));
1651 -- Link with g++ if C++ is one of the languages, otherwise
1652 -- building the library may fail with unresolved symbols.
1654 if C_Plus_Plus_Is_Used
then
1655 if Compiler_Names
(C_Plus_Plus_Language_Index
) = null then
1656 Get_Compiler
(C_Plus_Plus_Language_Index
);
1659 if Compiler_Is_Gcc
(C_Plus_Plus_Language_Index
) then
1661 Add_Str_To_Name_Buffer
1662 (Compiler_Names
(C_Plus_Plus_Language_Index
).all);
1663 Driver_Name
:= Name_Find
;
1667 -- If Library_Options is specified, add these options
1670 Library_Options
: constant Variable_Value
:=
1672 (Name_Library_Options
,
1673 Data
.Decl
.Attributes
,
1677 if not Library_Options
.Default
then
1679 Current
: String_List_Id
;
1680 Element
: String_Element
;
1683 Current
:= Library_Options
.Values
;
1684 while Current
/= Nil_String
loop
1686 Project_Tree
.String_Elements
.Table
(Current
);
1687 Get_Name_String
(Element
.Value
);
1689 if Name_Len
/= 0 then
1690 Library_Opts
.Increment_Last
;
1691 Library_Opts
.Table
(Library_Opts
.Last
) :=
1692 new String'(Name_Buffer (1 .. Name_Len));
1695 Current := Element.Next;
1701 new Argument_List'(Argument_List
1702 (Library_Opts
.Table
(1 .. Library_Opts
.Last
)));
1705 MLib
.Tgt
.Build_Dynamic_Library
1706 (Ofiles
=> Arguments
(1 .. Last_Argument
),
1707 Options
=> Lib_Opts
.all,
1708 Interfaces
=> No_Argument
,
1709 Lib_Filename
=> Get_Name_String
(Data
.Library_Name
),
1710 Lib_Dir
=> Get_Name_String
(Data
.Library_Dir
),
1711 Symbol_Data
=> No_Symbols
,
1712 Driver_Name
=> Driver_Name
,
1714 Auto_Init
=> False);
1718 -- Create fake empty archive, so we can check its time stamp later
1721 Archive
: Ada
.Text_IO
.File_Type
;
1723 Create
(Archive
, Out_File
, Archive_Name
);
1727 Create_Archive_Dependency_File
1728 (Archive_Dep_Name
, Data
.First_Other_Source
);
1736 procedure Check
(Option
: String) is
1737 First
: Positive := Option
'First;
1741 for Index
in Option
'First + 1 .. Option
'Last - 1 loop
1742 if Option
(Index
) = ' ' and then Option
(Index
+ 1) = '-' then
1743 Write_Str
("warning: switch """);
1745 Write_Str
(""" is suspicious; consider using ");
1748 while Last
<= Option
'Last loop
1749 if Option
(Last
) = ' ' then
1750 if First
/= Option
'First then
1755 Write_Str
(Option
(First
.. Last
- 1));
1758 while Last
<= Option
'Last and then Option
(Last
) = ' ' loop
1765 if Last
= Option
'Last then
1766 if First
/= Option
'First then
1771 Write_Str
(Option
(First
.. Last
));
1779 Write_Line
(" instead");
1785 ---------------------------
1786 -- Check_Archive_Builder --
1787 ---------------------------
1789 procedure Check_Archive_Builder
is
1791 -- First, make sure that the archive builder (ar) is on the path
1793 if Archive_Builder_Path
= null then
1794 Archive_Builder_Path
:= Locate_Exec_On_Path
(Archive_Builder
);
1796 if Archive_Builder_Path
= null then
1798 ("unable to locate archive builder """,
1803 -- If there is an archive indexer (ranlib), try to locate it on the
1804 -- path. Don't fail if it is not found.
1806 if Archive_Indexer
/= "" then
1807 Archive_Indexer_Path
:= Locate_Exec_On_Path
(Archive_Indexer
);
1810 end Check_Archive_Builder
;
1812 ------------------------------
1813 -- Check_Compilation_Needed --
1814 ------------------------------
1816 procedure Check_Compilation_Needed
1817 (Source
: Other_Source
;
1818 Need_To_Compile
: out Boolean)
1820 Source_Name
: constant String := Get_Name_String
(Source
.File_Name
);
1821 Source_Path
: constant String := Get_Name_String
(Source
.Path_Name
);
1822 Object_Name
: constant String := Get_Name_String
(Source
.Object_Name
);
1823 C_Object_Name
: String := Object_Name
;
1824 Dep_Name
: constant String := Get_Name_String
(Source
.Dep_Name
);
1825 C_Source_Path
: String := Source_Path
;
1827 Source_In_Dependencies
: Boolean := False;
1828 -- Set True if source was found in dependency file of its object file
1830 Dep_File
: Prj
.Util
.Text_File
;
1834 Looping
: Boolean := False;
1835 -- Set to True at the end of the first Big_Loop
1838 Canonical_Case_File_Name
(C_Source_Path
);
1839 Canonical_Case_File_Name
(C_Object_Name
);
1841 -- Assume the worst, so that statement "return;" may be used if there
1844 Need_To_Compile
:= True;
1846 if Verbose_Mode
then
1847 Write_Str
(" Checking ");
1848 Write_Str
(Source_Name
);
1849 Write_Line
(" ... ");
1852 -- If object file does not exist, of course source need to be compiled
1854 if Source
.Object_TS
= Empty_Time_Stamp
then
1855 if Verbose_Mode
then
1856 Write_Str
(" -> object file ");
1857 Write_Str
(Object_Name
);
1858 Write_Line
(" does not exist");
1864 -- If the object file has been created before the last modification
1865 -- of the source, the source need to be recompiled.
1867 if Source
.Object_TS
< Source
.Source_TS
then
1868 if Verbose_Mode
then
1869 Write_Str
(" -> object file ");
1870 Write_Str
(Object_Name
);
1871 Write_Line
(" has time stamp earlier than source");
1877 -- If there is no dependency file, then the source needs to be
1878 -- recompiled and the dependency file need to be created.
1880 if Source
.Dep_TS
= Empty_Time_Stamp
then
1881 if Verbose_Mode
then
1882 Write_Str
(" -> dependency file ");
1883 Write_Str
(Dep_Name
);
1884 Write_Line
(" does not exist");
1890 -- The source needs to be recompiled if the source has been modified
1891 -- after the dependency file has been created.
1893 if Source
.Dep_TS
< Source
.Source_TS
then
1894 if Verbose_Mode
then
1895 Write_Str
(" -> dependency file ");
1896 Write_Str
(Dep_Name
);
1897 Write_Line
(" has time stamp earlier than source");
1903 -- Look for all dependencies
1905 Open
(Dep_File
, Dep_Name
);
1907 -- If dependency file cannot be open, we need to recompile the source
1909 if not Is_Valid
(Dep_File
) then
1910 if Verbose_Mode
then
1911 Write_Str
(" -> could not open dependency file ");
1912 Write_Line
(Dep_Name
);
1918 -- Loop Big_Loop is executed several times only when the dependency file
1919 -- contains several times
1920 -- <object file>: <source1> ...
1921 -- When there is only one of such occurence, Big_Loop is exited
1922 -- successfully at the beginning of the second loop.
1927 End_Of_File_Reached
: Boolean := False;
1931 if End_Of_File
(Dep_File
) then
1932 End_Of_File_Reached
:= True;
1936 Get_Line
(Dep_File
, Name_Buffer
, Name_Len
);
1938 exit when Name_Len
> 0 and then Name_Buffer
(1) /= '#';
1941 -- If dependency file contains only empty lines or comments, then
1942 -- dependencies are unknown, and the source needs to be
1945 if End_Of_File_Reached
then
1946 -- If we have reached the end of file after the first loop,
1947 -- there is nothing else to do.
1949 exit Big_Loop
when Looping
;
1951 if Verbose_Mode
then
1952 Write_Str
(" -> dependency file ");
1953 Write_Str
(Dep_Name
);
1954 Write_Line
(" is empty");
1963 Finish
:= Index
(Name_Buffer
(1 .. Name_Len
), ": ");
1966 Canonical_Case_File_Name
(Name_Buffer
(1 .. Finish
- 1));
1969 -- First line must start with name of object file, followed by colon
1971 if Finish
= 0 or else
1972 Name_Buffer
(1 .. Finish
- 1) /= C_Object_Name
1974 if Verbose_Mode
then
1975 Write_Str
(" -> dependency file ");
1976 Write_Str
(Dep_Name
);
1977 Write_Line
(" has wrong format");
1984 Start
:= Finish
+ 2;
1986 -- Process each line
1990 Line
: String := Name_Buffer
(1 .. Name_Len
);
1991 Last
: Natural := Name_Len
;
1996 -- Find the beginning of the next source path name
1998 while Start
< Last
and then Line
(Start
) = ' ' loop
2002 -- Go to next line when there is a continuation character
2003 -- \ at the end of the line.
2005 exit Name_Loop
when Start
= Last
2006 and then Line
(Start
) = '\';
2008 -- We should not be at the end of the line, without
2009 -- a continuation character \.
2011 if Start
= Last
then
2012 if Verbose_Mode
then
2013 Write_Str
(" -> dependency file ");
2014 Write_Str
(Dep_Name
);
2015 Write_Line
(" has wrong format");
2022 -- Look for the end of the source path name
2025 while Finish
< Last
loop
2026 if Line
(Finish
) = '\' then
2028 -- On Windows, a '\' is part of the path name,
2029 -- except when it is followed by another '\' or by
2030 -- a space. On other platforms, when we are getting
2031 -- a '\' that is not the last character of the
2032 -- line, the next character is part of the path
2033 -- name, even if it is a space.
2036 and then Line
(Finish
+ 1) /= '\'
2037 and then Line
(Finish
+ 1) /= ' '
2039 Finish
:= Finish
+ 1;
2042 Line
(Finish
.. Last
- 1) :=
2043 Line
(Finish
+ 1 .. Last
);
2048 -- A space that is not preceded by '\' indicates
2049 -- the end of the path name.
2051 exit when Line
(Finish
+ 1) = ' ';
2053 Finish
:= Finish
+ 1;
2057 -- Check this source
2060 Src_Name
: constant String :=
2063 Line
(Start
.. Finish
),
2064 Resolve_Links
=> False,
2065 Case_Sensitive
=> False);
2066 Src_TS
: Time_Stamp_Type
;
2069 -- If it is original source, set
2070 -- Source_In_Dependencies.
2072 if Src_Name
= C_Source_Path
then
2073 Source_In_Dependencies
:= True;
2077 Add_Str_To_Name_Buffer
(Src_Name
);
2078 Src_TS
:= File_Stamp
(File_Name_Type
'(Name_Find));
2080 -- If the source does not exist, we need to recompile
2082 if Src_TS = Empty_Time_Stamp then
2083 if Verbose_Mode then
2084 Write_Str (" -> source ");
2085 Write_Str (Src_Name);
2086 Write_Line (" does not exist");
2092 -- If the source has been modified after the object
2093 -- file, we need to recompile.
2095 elsif Src_TS > Source.Object_TS then
2096 if Verbose_Mode then
2097 Write_Str (" -> source ");
2098 Write_Str (Src_Name);
2100 (" has time stamp later than object file");
2108 -- If the source path name ends the line, we are done
2110 exit Line_Loop when Finish = Last;
2112 -- Go get the next source on the line
2114 Start := Finish + 1;
2118 -- If we are here, we had a continuation character \ at the end
2119 -- of the line, so we continue with the next line.
2121 Get_Line (Dep_File, Name_Buffer, Name_Len);
2126 -- Set Looping at the end of the first loop
2132 -- If the original sources were not in the dependency file, then we
2133 -- need to recompile. It may mean that we are using a different source
2134 -- (different variant) for this object file.
2136 if not Source_In_Dependencies then
2137 if Verbose_Mode then
2138 Write_Str (" -> source ");
2139 Write_Str (Source_Path);
2140 Write_Line (" is not in the dependencies");
2146 -- If we are here, then everything is OK, no need to recompile
2148 if Verbose_Mode then
2149 Write_Line (" -> up to date");
2152 Need_To_Compile := False;
2153 end Check_Compilation_Needed;
2155 ---------------------------
2156 -- Check_For_C_Plus_Plus --
2157 ---------------------------
2159 procedure Check_For_C_Plus_Plus is
2161 C_Plus_Plus_Is_Used := False;
2163 for Project in Project_Table.First ..
2164 Project_Table.Last (Project_Tree.Projects)
2167 Project_Tree.Projects.Table (Project).Langs
2168 (C_Plus_Plus_Language_Index)
2170 C_Plus_Plus_Is_Used := True;
2174 end Check_For_C_Plus_Plus;
2181 (Source_Id : Other_Source_Id;
2182 Data : Project_Data;
2183 Local_Errors : in out Boolean)
2185 Source : Other_Source :=
2186 Project_Tree.Other_Sources.Table (Source_Id);
2188 CPATH : String_Access := null;
2191 -- If the compiler is not known yet, get its path name
2193 if Compiler_Names (Source.Language) = null then
2194 Get_Compiler (Source.Language);
2197 -- For non GCC compilers, get the dependency file, first calling the
2198 -- compiler with the switch -M.
2200 if not Compiler_Is_Gcc (Source.Language) then
2203 -- Add the source name, preceded by -M
2205 Add_Argument (Dash_M, True);
2206 Add_Argument (Get_Name_String (Source.Path_Name), True);
2208 -- Add the compiling switches for this source found in
2209 -- package Compiler of the project file, if they exist.
2212 (Data, Compiler, Source.Language, Source.File_Name);
2214 -- Add the compiling switches for the language specified
2215 -- on the command line, if any.
2218 J in 1 .. Comp_Opts.Last (Options (Source.Language))
2220 Add_Argument (Options (Source.Language).Table (J), True);
2223 -- Finally, add imported directory switches for this project file
2225 Add_Search_Directories (Data, Source.Language);
2227 -- And invoke the compiler using GNAT.Expect
2230 (Compiler_Names (Source.Language).all,
2231 Compiler_Paths (Source.Language));
2236 Compiler_Paths (Source.Language).all,
2237 Arguments (1 .. Last_Argument),
2239 Err_To_Out => True);
2242 Dep_File : Ada.Text_IO.File_Type;
2243 Result : Expect_Match;
2246 pragma Warnings (Off, Status);
2249 -- Create the dependency file
2251 Create (Dep_File, Out_File, Get_Name_String (Source.Dep_Name));
2254 Expect (FD, Result, Line_Matcher);
2256 exit when Result = Expect_Timeout;
2259 S : constant String := Strip_CR_LF (Expect_Out (FD));
2262 -- Each line of the output is put in the dependency
2263 -- file, including errors. If there are errors, the
2264 -- syntax of the dependency file will be incorrect and
2265 -- recompilation will occur automatically the next time
2266 -- the dependencies are checked.
2268 Put_Line (Dep_File, S);
2272 -- If we are here, it means we had a timeout, so the
2273 -- dependency file may be incomplete. It is safer to
2274 -- delete it, otherwise the dependencies may be wrong.
2278 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2281 when Process_Died =>
2283 -- This is the normal outcome. Just close the file
2290 -- Something wrong happened. It is safer to delete the
2291 -- dependency file, otherwise the dependencies may be wrong.
2295 if Is_Open (Dep_File) then
2299 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2303 -- If we cannot spawn the compiler, then the dependencies are
2304 -- not updated. It is safer then to delete the dependency file,
2305 -- otherwise the dependencies may be wrong.
2307 when Invalid_Process =>
2308 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2314 -- For GCC compilers, make sure the language is always specified to
2315 -- to the GCC driver, in case the extension is not recognized by the
2316 -- GCC driver as a source of the language.
2318 if Compiler_Is_Gcc (Source.Language) then
2319 Add_Argument (Dash_x, Verbose_Mode);
2321 (Get_Name_String (Language_Names.Table (Source.Language)),
2325 Add_Argument (Dash_c, True);
2327 -- Add the compiling switches for this source found in package Compiler
2328 -- of the project file, if they exist.
2331 (Data, Compiler, Source.Language, Source.File_Name);
2333 -- Specify the source to be compiled
2335 Add_Argument (Get_Name_String (Source.Path_Name), True);
2337 -- If non static library project, compile with the PIC option if there
2338 -- is one (when there is no PIC option, MLib.Tgt.PIC_Option returns an
2339 -- empty string, and Add_Argument with an empty string has no effect).
2341 if Data.Library and then Data.Library_Kind /= Static then
2342 Add_Argument (PIC_Option, True);
2345 -- Indicate the name of the object
2347 Add_Argument (Dash_o, True);
2348 Add_Argument (Get_Name_String (Source.Object_Name), True);
2350 -- When compiler is GCC, use the magic switch that creates the
2351 -- dependency file in the correct format.
2353 if Compiler_Is_Gcc (Source.Language) then
2355 ("-Wp,-MD," & Get_Name_String (Source.Dep_Name),
2359 -- Add the compiling switches for the language specified on the command
2362 for J in 1 .. Comp_Opts.Last (Options (Source.Language)) loop
2363 Add_Argument (Options (Source.Language).Table (J), True);
2366 -- Finally, add the imported directory switches for this project file
2367 -- (or, for gcc compilers, set up the CPATH env var if needed).
2369 Add_Search_Directories (Data, Source.Language);
2371 -- Set CPATH, if compiler is GCC
2373 if Compiler_Is_Gcc (Source.Language) then
2374 CPATH := Current_Include_Paths (Source.Language);
2377 -- And invoke the compiler
2380 (Name => Compiler_Names (Source.Language).all,
2381 Path => Compiler_Paths (Source.Language),
2385 (Compiler_Paths (Source.Language).all,
2386 Arguments (1 .. Last_Argument),
2389 -- Case of successful compilation
2393 -- Update the time stamp of the object file
2395 Source.Object_TS := File_Stamp (Source.Object_Name);
2397 -- Do some sanity checks
2399 if Source.Object_TS = Empty_Time_Stamp then
2400 Local_Errors := True;
2403 Get_Name_String (Source.Object_Name),
2404 " has not been created");
2406 elsif Source.Object_TS < Source.Source_TS then
2407 Local_Errors := True;
2410 Get_Name_String (Source.Object_Name),
2411 " has not been modified");
2414 -- Everything looks fine, update the Other_Sources table
2416 Project_Tree.Other_Sources.Table (Source_Id) := Source;
2419 -- Compilation failed
2422 Local_Errors := True;
2425 Get_Name_String (Source.Path_Name),
2430 --------------------------------
2431 -- Compile_Individual_Sources --
2432 --------------------------------
2434 procedure Compile_Individual_Sources is
2435 Data : Project_Data :=
2436 Project_Tree.Projects.Table (Main_Project);
2437 Source_Id : Other_Source_Id;
2438 Source : Other_Source;
2439 Source_Name : File_Name_Type;
2440 Project_Name : String := Get_Name_String (Data.Name);
2441 Dummy : Boolean := False;
2443 Ada_Is_A_Language : constant Boolean :=
2444 Data.Langs (Ada_Language_Index);
2448 To_Mixed (Project_Name);
2449 Compile_Only := True;
2451 Get_Imported_Directories (Main_Project, Data);
2452 Project_Tree.Projects.Table (Main_Project) := Data;
2454 -- Compilation will occur in the object directory
2456 if Project_Of_Current_Object_Directory /= Main_Project then
2457 Project_Of_Current_Object_Directory := Main_Project;
2458 Change_Dir (Get_Name_String (Data.Object_Directory));
2460 if Verbose_Mode then
2461 Write_Str ("Changing to object directory of """);
2462 Write_Name (Data.Name);
2463 Write_Str (""": """);
2464 Write_Name (Data.Display_Object_Dir);
2469 if not Data.Other_Sources_Present then
2470 if Ada_Is_A_Language then
2475 Main : constant String := Mains.Next_Main;
2477 exit when Main'Length = 0;
2478 Ada_Mains.Increment_Last;
2479 Ada_Mains.Table (Ada_Mains.Last) := new String'(Main
);
2484 Osint
.Fail
("project ", Project_Name
, " contains no source");
2492 Main
: constant String := Mains
.Next_Main
;
2494 Name_Len
:= Main
'Length;
2495 exit when Name_Len
= 0;
2496 Name_Buffer
(1 .. Name_Len
) := Main
;
2497 Canonical_Case_File_Name
(Name_Buffer
(1 .. Name_Len
));
2498 Source_Name
:= Name_Find
;
2500 if not Sources_Compiled
.Get
(Source_Name
) then
2501 Sources_Compiled
.Set
(Source_Name
, True);
2503 Source_Id
:= Data
.First_Other_Source
;
2504 while Source_Id
/= No_Other_Source
loop
2505 Source
:= Project_Tree
.Other_Sources
.Table
(Source_Id
);
2506 exit when Source
.File_Name
= Source_Name
;
2507 Source_Id
:= Source
.Next
;
2510 if Source_Id
= No_Other_Source
then
2511 if Ada_Is_A_Language
then
2512 Ada_Mains
.Increment_Last
;
2513 Ada_Mains
.Table
(Ada_Mains
.Last
) := new String'(Main);
2518 " is not a valid source of project ",
2523 Compile (Source_Id, Data, Dummy);
2530 if Ada_Mains.Last > 0 then
2532 -- Invoke gnatmake for all Ada sources
2535 Add_Argument (Dash_u, True);
2537 for Index in 1 .. Ada_Mains.Last loop
2538 Add_Argument (Ada_Mains.Table (Index), True);
2541 Compile_Link_With_Gnatmake (Mains_Specified => False);
2543 end Compile_Individual_Sources;
2545 --------------------------------
2546 -- Compile_Link_With_Gnatmake --
2547 --------------------------------
2549 procedure Compile_Link_With_Gnatmake (Mains_Specified : Boolean) is
2550 Data : constant Project_Data :=
2551 Project_Tree.Projects.Table (Main_Project);
2555 -- Array Arguments may already contain some arguments, so we don't
2556 -- set Last_Argument to 0.
2558 -- Get the gnatmake to invoke
2560 Get_Compiler (Ada_Language_Index);
2562 -- Specify the project file
2564 Add_Argument (Dash_P, True);
2565 Add_Argument (Get_Name_String (Data.Display_Path_Name), True);
2567 -- Add the saved switches, if any
2569 for Index in 1 .. Saved_Switches.Last loop
2570 Add_Argument (Saved_Switches.Table (Index), True);
2573 -- If Mains_Specified is True, find the mains in package Mains
2575 if Mains_Specified then
2580 Main : constant String := Mains.Next_Main;
2582 exit when Main'Length = 0;
2583 Add_Argument (Main, True);
2588 -- Specify output file name, if any was specified on the command line
2590 if Output_File_Name /= null then
2591 Add_Argument (Dash_o, True);
2592 Add_Argument (Output_File_Name, True);
2595 -- Transmit some switches to gnatmake
2599 if Compile_Only then
2600 Add_Argument (Dash_c, True);
2605 if Display_Compilation_Progress then
2606 Add_Argument (Dash_d, True);
2612 Add_Argument (Dash_k, True);
2617 if Force_Compilations then
2618 Add_Argument (Dash_f, True);
2623 if Verbose_Mode then
2624 Add_Argument (Dash_v, True);
2629 if Quiet_Output then
2630 Add_Argument (Dash_q, True);
2635 case Current_Verbosity is
2640 Add_Argument (Dash_vP1, True);
2643 Add_Argument (Dash_vP2, True);
2646 -- If there are compiling options for Ada, transmit them to gnatmake
2648 if Comp_Opts.Last (Options (Ada_Language_Index)) /= 0 then
2649 Add_Argument (Dash_cargs, True);
2651 for Arg in 1 .. Comp_Opts.Last (Options (Ada_Language_Index)) loop
2652 Add_Argument (Options (Ada_Language_Index).Table (Arg), True);
2656 if not Compile_Only then
2660 if Linker_Options.Last /= 0 then
2661 Add_Argument (Dash_largs, True);
2663 Add_Argument (Dash_largs, Verbose_Mode);
2668 Add_Archives (For_Gnatmake => True);
2670 -- If there are linking options from the command line,
2671 -- transmit them to gnatmake.
2673 for Arg in 1 .. Linker_Options.Last loop
2674 Add_Argument (Linker_Options.Table (Arg), True);
2678 -- And invoke gnatmake
2681 (Compiler_Names (Ada_Language_Index).all,
2682 Compiler_Paths (Ada_Language_Index));
2685 (Compiler_Paths (Ada_Language_Index).all,
2686 Arguments (1 .. Last_Argument),
2689 -- Report an error if call to gnatmake failed
2694 Compiler_Names (Ada_Language_Index).all,
2697 end Compile_Link_With_Gnatmake;
2699 ---------------------
2700 -- Compile_Sources --
2701 ---------------------
2703 procedure Compile_Sources is
2704 Data : Project_Data;
2705 Source_Id : Other_Source_Id;
2706 Source : Other_Source;
2708 Local_Errors : Boolean := False;
2709 -- Set to True when there is a compilation error. Used only when
2710 -- Keep_Going is True, to inhibit the building of the archive.
2712 Need_To_Compile : Boolean;
2713 -- Set to True when a source needs to be compiled/recompiled
2715 Need_To_Rebuild_Archive : Boolean := Force_Compilations;
2716 -- True when the archive needs to be built/rebuilt unconditionally
2718 Total_Number_Of_Sources : Int := 0;
2720 Current_Source_Number : Int := 0;
2723 -- First, get the number of sources
2725 for Project in Project_Table.First ..
2726 Project_Table.Last (Project_Tree.Projects)
2728 Data := Project_Tree.Projects.Table (Project);
2730 if not Data.Virtual and then Data.Other_Sources_Present then
2731 Source_Id := Data.First_Other_Source;
2732 while Source_Id /= No_Other_Source loop
2733 Source := Project_Tree.Other_Sources.Table (Source_Id);
2734 Total_Number_Of_Sources := Total_Number_Of_Sources + 1;
2735 Source_Id := Source.Next;
2740 -- Loop through project files
2742 for Project in Project_Table.First ..
2743 Project_Table.Last (Project_Tree.Projects)
2745 Local_Errors := False;
2746 Data := Project_Tree.Projects.Table (Project);
2748 -- Nothing to do when no sources of language other than Ada
2750 if (not Data.Virtual) and then Data.Other_Sources_Present then
2752 -- If the imported directory switches are unknown, compute them
2754 if not Data.Include_Data_Set then
2755 Get_Imported_Directories (Project, Data);
2756 Data.Include_Data_Set := True;
2757 Project_Tree.Projects.Table (Project) := Data;
2760 Need_To_Rebuild_Archive := Force_Compilations;
2762 -- Compilation will occur in the object directory
2764 if Project_Of_Current_Object_Directory /= Project then
2765 Project_Of_Current_Object_Directory := Project;
2766 Change_Dir (Get_Name_String (Data.Object_Directory));
2768 if Verbose_Mode then
2769 Write_Str ("Changing to object directory of """);
2770 Write_Name (Data.Display_Name);
2771 Write_Str (""": """);
2772 Write_Name (Data.Display_Object_Dir);
2777 -- Process each source one by one
2779 Source_Id := Data.First_Other_Source;
2780 while Source_Id /= No_Other_Source loop
2781 Source := Project_Tree.Other_Sources.Table (Source_Id);
2782 Current_Source_Number := Current_Source_Number + 1;
2783 Need_To_Compile := Force_Compilations;
2785 -- Check if compilation is needed
2787 if not Need_To_Compile then
2788 Check_Compilation_Needed (Source, Need_To_Compile);
2791 -- Proceed, if compilation is needed
2793 if Need_To_Compile then
2795 -- If a source is compiled/recompiled, of course the
2796 -- archive will need to be built/rebuilt.
2798 Need_To_Rebuild_Archive := True;
2799 Compile (Source_Id, Data, Local_Errors);
2802 if Display_Compilation_Progress then
2803 Write_Str ("completed ");
2804 Write_Int (Current_Source_Number);
2805 Write_Str (" out of ");
2806 Write_Int (Total_Number_Of_Sources);
2809 ((Current_Source_Number * 100) / Total_Number_Of_Sources);
2810 Write_Str ("%)...");
2814 -- Next source, if any
2816 Source_Id := Source.Next;
2819 if Need_To_Rebuild_Archive and then (not Data.Library) then
2820 Need_To_Rebuild_Global_Archive := True;
2823 -- If there was no compilation error and -c was not used,
2824 -- build / rebuild the archive if necessary.
2827 and then Data.Library
2828 and then not Data.Langs (Ada_Language_Index)
2829 and then not Compile_Only
2831 Build_Library (Project, Need_To_Rebuild_Archive);
2835 end Compile_Sources;
2841 procedure Copyright is
2843 -- Only output the Copyright notice once
2845 if not Copyright_Output then
2846 Copyright_Output := True;
2848 Write_Str ("GPRMAKE ");
2849 Write_Str (Gnatvsn.Gnat_Version_String);
2850 Write_Str (" Copyright 2004-");
2851 Write_Str (Gnatvsn.Current_Year);
2852 Write_Str (" Free Software Foundation, Inc.");
2857 ------------------------------------
2858 -- Create_Archive_Dependency_File --
2859 ------------------------------------
2861 procedure Create_Archive_Dependency_File
2863 First_Source : Other_Source_Id)
2865 Source_Id : Other_Source_Id;
2866 Source : Other_Source;
2867 Dep_File : Ada.Text_IO.File_Type;
2870 -- Create the file in Append mode, to avoid automatic insertion of
2871 -- an end of line if file is empty.
2873 Create (Dep_File, Append_File, Name);
2875 Source_Id := First_Source;
2876 while Source_Id /= No_Other_Source loop
2877 Source := Project_Tree.Other_Sources.Table (Source_Id);
2878 Put_Line (Dep_File, Get_Name_String (Source.Object_Name));
2879 Put_Line (Dep_File, String (Source.Object_TS));
2880 Source_Id := Source.Next;
2887 if Is_Open (Dep_File) then
2890 end Create_Archive_Dependency_File;
2892 -------------------------------------------
2893 -- Create_Global_Archive_Dependency_File --
2894 -------------------------------------------
2896 procedure Create_Global_Archive_Dependency_File (Name : String) is
2897 Source_Id : Other_Source_Id;
2898 Source : Other_Source;
2899 Dep_File : Ada.Text_IO.File_Type;
2902 -- Create the file in Append mode, to avoid automatic insertion of
2903 -- an end of line if file is empty.
2905 Create (Dep_File, Append_File, Name);
2907 -- Get all the object files of non-Ada sources in non-library projects
2909 for Project in Project_Table.First ..
2910 Project_Table.Last (Project_Tree.Projects)
2912 if not Project_Tree.Projects.Table (Project).Library then
2914 Project_Tree.Projects.Table (Project).First_Other_Source;
2915 while Source_Id /= No_Other_Source loop
2916 Source := Project_Tree.Other_Sources.Table (Source_Id);
2918 -- Put only those object files that are in the global archive
2920 if Is_Included_In_Global_Archive
2921 (Source.Object_Name, Project)
2923 Put_Line (Dep_File, Get_Name_String (Source.Object_Path));
2924 Put_Line (Dep_File, String (Source.Object_TS));
2927 Source_Id := Source.Next;
2936 if Is_Open (Dep_File) then
2939 end Create_Global_Archive_Dependency_File;
2941 ---------------------
2942 -- Display_Command --
2943 ---------------------
2945 procedure Display_Command
2947 Path : String_Access;
2948 CPATH : String_Access := null;
2949 Ellipse : Boolean := False)
2951 Display_Ellipse : Boolean := Ellipse;
2954 -- Only display the command in Verbose Mode (-v) or when
2955 -- not in Quiet Output (no -q).
2957 if Verbose_Mode or (not Quiet_Output) then
2959 -- In Verbose Mode output the full path of the spawned process
2961 if Verbose_Mode then
2962 if CPATH /= null then
2963 Write_Str ("CPATH = ");
2964 Write_Line (CPATH.all);
2967 Write_Str (Path.all);
2973 -- Display only the arguments for which the display flag is set
2974 -- (in Verbose Mode, the display flag is set for all arguments)
2976 for Arg in 1 .. Last_Argument loop
2977 if Arguments_Displayed (Arg) then
2979 Write_Str (Arguments (Arg).all);
2981 elsif Display_Ellipse then
2983 Display_Ellipse := False;
2989 end Display_Command;
2995 procedure Get_Compiler (For_Language : First_Language_Indexes) is
2996 Data : constant Project_Data :=
2997 Project_Tree.Projects.Table (Main_Project);
2999 Ide : constant Package_Id :=
3002 In_Packages => Data.Decl.Packages,
3003 In_Tree => Project_Tree);
3004 -- The id of the package IDE in the project file
3006 Compiler : constant Variable_Value :=
3008 (Name => Language_Names.Table (For_Language),
3010 Attribute_Or_Array_Name => Name_Compiler_Command,
3012 In_Tree => Project_Tree);
3013 -- The value of Compiler_Command ("language") in package IDE, if defined
3016 -- No need to do it again if the compiler is known for this language
3018 if Compiler_Names (For_Language) = null then
3020 -- If compiler command is not defined for this language in package
3021 -- IDE, use the default compiler for this language.
3023 if Compiler = Nil_Variable_Value then
3024 if For_Language in Default_Compiler_Names'Range then
3025 Compiler_Names (For_Language) :=
3026 Default_Compiler_Names (For_Language);
3030 ("unknow compiler name for language """,
3031 Get_Name_String (Language_Names.Table (For_Language)),
3036 Compiler_Names (For_Language) :=
3037 new String'(Get_Name_String
(Compiler
.Value
));
3040 -- Check we have a GCC compiler (name ends with "gcc" or "g++")
3043 Comp_Name
: constant String := Compiler_Names
(For_Language
).all;
3044 Last3
: String (1 .. 3);
3046 if Comp_Name
'Length >= 3 then
3047 Last3
:= Comp_Name
(Comp_Name
'Last - 2 .. Comp_Name
'Last);
3048 Compiler_Is_Gcc
(For_Language
) :=
3049 (Last3
= "gcc") or (Last3
= "g++");
3051 Compiler_Is_Gcc
(For_Language
) := False;
3055 -- Locate the compiler on the path
3057 Compiler_Paths
(For_Language
) :=
3058 Locate_Exec_On_Path
(Compiler_Names
(For_Language
).all);
3060 -- Fail if compiler cannot be found
3062 if Compiler_Paths
(For_Language
) = null then
3063 if For_Language
= Ada_Language_Index
then
3065 ("unable to locate """,
3066 Compiler_Names
(For_Language
).all,
3071 ("unable to locate " &
3072 Get_Name_String
(Language_Names
.Table
(For_Language
)),
3073 " compiler """, Compiler_Names
(For_Language
).all & '"');
3079 ------------------------------
3080 -- Get_Imported_Directories --
3081 ------------------------------
3083 procedure Get_Imported_Directories
3084 (Project
: Project_Id
;
3085 Data
: in out Project_Data
)
3087 Imported_Projects
: Project_List
:= Data
.Imported_Projects
;
3089 Path_Length
: Natural := 0;
3090 Position
: Natural := 0;
3092 procedure Add
(Source_Dirs
: String_List_Id
);
3093 -- Add a list of source directories
3095 procedure Recursive_Get_Dirs
(Prj
: Project_Id
);
3096 -- Recursive procedure to get the source directories of this project
3097 -- file and of the project files it imports, in the correct order.
3103 procedure Add
(Source_Dirs
: String_List_Id
) is
3104 Element_Id
: String_List_Id
;
3105 Element
: String_Element
;
3106 Add_Arg
: Boolean := True;
3109 -- Add each source directory path name, preceded by "-I" to Arguments
3111 Element_Id
:= Source_Dirs
;
3112 while Element_Id
/= Nil_String
loop
3113 Element
:= Project_Tree
.String_Elements
.Table
(Element_Id
);
3115 if Element
.Value
/= No_Name
then
3116 Get_Name_String
(Element
.Display_Value
);
3118 if Name_Len
> 0 then
3120 -- Remove a trailing directory separator: this may cause
3121 -- problems on Windows.
3124 and then Name_Buffer
(Name_Len
) = Directory_Separator
3126 Name_Len
:= Name_Len
- 1;
3130 Arg
: constant String :=
3131 "-I" & Name_Buffer
(1 .. Name_Len
);
3133 -- Check if directory is already in the list. If it is,
3134 -- no need to put it there again.
3138 for Index
in 1 .. Last_Argument
loop
3139 if Arguments
(Index
).all = Arg
then
3146 if Path_Length
/= 0 then
3147 Path_Length
:= Path_Length
+ 1;
3150 Path_Length
:= Path_Length
+ Name_Len
;
3152 Add_Argument
(Arg
, True);
3158 Element_Id
:= Element
.Next
;
3162 ------------------------
3163 -- Recursive_Get_Dirs --
3164 ------------------------
3166 procedure Recursive_Get_Dirs
(Prj
: Project_Id
) is
3167 Data
: Project_Data
;
3168 Imported
: Project_List
;
3171 -- Nothing to do if project is undefined
3173 if Prj
/= No_Project
then
3174 Data
:= Project_Tree
.Projects
.Table
(Prj
);
3176 -- Nothing to do if project has already been processed
3178 if not Data
.Seen
then
3180 -- Mark the project as processed, to avoid multiple processing
3181 -- of the same project.
3183 Project_Tree
.Projects
.Table
(Prj
).Seen
:= True;
3185 -- Add the source directories of this project
3187 if not Data
.Virtual
then
3188 Add
(Data
.Source_Dirs
);
3191 Recursive_Get_Dirs
(Data
.Extends
);
3193 -- Call itself for all imported projects, if any
3195 Imported
:= Data
.Imported_Projects
;
3196 while Imported
/= Empty_Project_List
loop
3198 (Project_Tree
.Project_Lists
.Table
(Imported
).Project
);
3200 Project_Tree
.Project_Lists
.Table
(Imported
).Next
;
3204 end Recursive_Get_Dirs
;
3206 -- Start of processing for Get_Imported_Directories
3209 -- First, mark all project as not processed
3211 for J
in Project_Table
.First
..
3212 Project_Table
.Last
(Project_Tree
.Projects
)
3214 Project_Tree
.Projects
.Table
(J
).Seen
:= False;
3221 -- Process this project individually, project data are already known
3223 Project_Tree
.Projects
.Table
(Project
).Seen
:= True;
3225 Add
(Data
.Source_Dirs
);
3227 Recursive_Get_Dirs
(Data
.Extends
);
3229 while Imported_Projects
/= Empty_Project_List
loop
3231 (Project_Tree
.Project_Lists
.Table
3232 (Imported_Projects
).Project
);
3233 Imported_Projects
:= Project_Tree
.Project_Lists
.Table
3234 (Imported_Projects
).Next
;
3237 Data
.Imported_Directories_Switches
:=
3238 new Argument_List
'(Arguments (1 .. Last_Argument));
3240 -- Create the Include_Path, from the Arguments
3242 Data.Include_Path := new String (1 .. Path_Length);
3243 Data.Include_Path (1 .. Arguments (1)'Length - 2) :=
3244 Arguments (1)(Arguments (1)'First + 2 .. Arguments (1)'Last);
3245 Position := Arguments (1)'Length - 2;
3247 for Arg in 2 .. Last_Argument loop
3248 Position := Position + 1;
3249 Data.Include_Path (Position) := Path_Separator;
3251 (Position + 1 .. Position + Arguments (Arg)'Length - 2) :=
3252 Arguments (Arg)(Arguments (Arg)'First + 2 .. Arguments (Arg)'Last);
3253 Position := Position + Arguments (Arg)'Length - 2;
3257 end Get_Imported_Directories;
3263 procedure Gprmake is
3267 if Verbose_Mode then
3269 Write_Str ("Parsing project file """);
3270 Write_Str (Project_File_Name.all);
3275 -- Parse and process project files for other languages (not for Ada)
3278 (Project => Main_Project,
3279 In_Tree => Project_Tree,
3280 Project_File_Name => Project_File_Name.all,
3281 Packages_To_Check => Packages_To_Check);
3283 -- Fail if parsing/processing was unsuccessful
3285 if Main_Project = No_Project then
3286 Osint.Fail ("""", Project_File_Name.all, """ processing failed");
3289 if Verbose_Mode then
3291 Write_Str ("Parsing of project file """);
3292 Write_Str (Project_File_Name.all);
3293 Write_Str (""" is finished.");
3297 -- If -f was specified, we will certainly need to link (except when
3298 -- -u or -c were specified, of course).
3300 Need_To_Relink := Force_Compilations;
3302 if Unique_Compile then
3303 if Mains.Number_Of_Mains = 0 then
3305 ("No source specified to compile in 'unique compile
' mode");
3307 Compile_Individual_Sources;
3308 Report_Total_Errors ("compilation");
3313 Data : constant Prj.Project_Data :=
3314 Project_Tree.Projects.Table (Main_Project);
3316 if Data.Library and then Mains.Number_Of_Mains /= 0 then
3318 ("Cannot specify mains on the command line " &
3319 "for a Library Project");
3322 -- First check for C++, to link libraries with g++,
3325 Check_For_C_Plus_Plus;
3327 -- Compile sources and build archives for library project,
3332 -- When Keep_Going is True, if we had some errors, fail now,
3333 -- reporting the number of compilation errors.
3334 -- Do not attempt to link.
3336 Report_Total_Errors ("compilation");
3338 -- If -c was not specified, link the executables,
3339 -- if there are any.
3342 and then not Data.Library
3343 and then Data.Object_Directory /= No_Path
3345 Build_Global_Archive;
3349 -- When Keep_Going is True, if we had some errors, fail, reporting
3350 -- the number of linking errors.
3352 Report_Total_Errors ("linking");
3361 procedure Initialize is
3363 Set_Mode (Ada_Only);
3365 -- Do some necessary package initializations
3370 Prj.Initialize (Project_Tree);
3373 -- Add the directory where gprmake is invoked in front of the path,
3374 -- if gprmake is invoked from a bin directory or with directory
3375 -- information. information. Only do this if the platform is not VMS,
3376 -- where the notion of path does not really exist.
3378 -- Below code shares nasty code duplication with make.adb code???
3382 Prefix : constant String := Executable_Prefix_Path;
3383 Command : constant String := Command_Name;
3386 if Prefix'Length > 0 then
3388 PATH : constant String :=
3389 Prefix & Directory_Separator & "bin" &
3391 Getenv ("PATH").all;
3393 Setenv ("PATH", PATH);
3397 for Index in reverse Command'Range loop
3398 if Command (Index) = Directory_Separator then
3400 Absolute_Dir : constant String :=
3402 (Command (Command'First .. Index));
3403 PATH : constant String :=
3406 Getenv ("PATH").all;
3408 Setenv ("PATH", PATH);
3418 -- Set Name_Ide and Name_Compiler_Command
3421 Add_Str_To_Name_Buffer ("ide");
3422 Name_Ide := Name_Find;
3425 Add_Str_To_Name_Buffer ("compiler_command");
3426 Name_Compiler_Command := Name_Find;
3428 -- Make sure the Saved_Switches table is empty
3430 Saved_Switches.Set_Last (0);
3432 -- Get the command line arguments
3434 Scan_Args : for Next_Arg in 1 .. Argument_Count loop
3435 Scan_Arg (Argument (Next_Arg));
3438 -- Fail if command line ended with "-P"
3440 if Project_File_Name_Expected then
3441 Osint.Fail ("project file name missing after -P");
3443 -- Or if it ended with "-o"
3445 elsif Output_File_Name_Expected then
3446 Osint.Fail ("output file name missing after -o");
3449 -- If no project file was specified, display the usage and fail
3451 if Project_File_Name = null then
3453 Exit_Program (E_Success);
3456 -- To be able of finding libgnat.a in MLib.Tgt, we need to have the
3457 -- default search dirs established in Osint.
3459 Osint.Add_Default_Search_Dirs;
3462 -----------------------------------
3463 -- Is_Included_In_Global_Archive --
3464 -----------------------------------
3466 function Is_Included_In_Global_Archive
3467 (Object_Name : File_Name_Type;
3468 Project : Project_Id) return Boolean
3470 Data : Project_Data := Project_Tree.Projects.Table (Project);
3471 Source : Other_Source_Id;
3474 while Data.Extended_By /= No_Project loop
3475 Data := Project_Tree.Projects.Table (Data.Extended_By);
3477 Source := Data.First_Other_Source;
3478 while Source /= No_Other_Source loop
3479 if Project_Tree.Other_Sources.Table (Source).Object_Name =
3485 Project_Tree.Other_Sources.Table (Source).Next;
3491 end Is_Included_In_Global_Archive;
3493 ----------------------
3494 -- Link_Executables --
3495 ----------------------
3497 procedure Link_Executables is
3498 Data : constant Project_Data :=
3499 Project_Tree.Projects.Table (Main_Project);
3501 Mains_Specified : constant Boolean := Mains.Number_Of_Mains /= 0;
3502 -- True if main sources were specified on the command line
3504 Object_Dir : constant String :=
3505 Get_Name_String (Data.Display_Object_Dir);
3506 -- Path of the object directory of the main project
3508 Source_Id : Other_Source_Id;
3509 Source : Other_Source;
3512 Linker_Name : String_Access;
3513 Linker_Path : String_Access;
3514 -- The linker name and path, when linking is not done by gnatlink
3516 Link_Done : Boolean := False;
3517 -- Set to True when the linker is invoked directly (not through
3518 -- gnatmake) to be able to report if mains were up to date at the end
3521 procedure Add_C_Plus_Plus_Link_For_Gnatmake;
3522 -- Add the --LINK= switch for gnatlink, depending on the C++ compiler
3524 procedure Check_Time_Stamps (Exec_Time_Stamp : Time_Stamp_Type);
3525 -- Check if there is an archive that is more recent than the executable
3526 -- to decide if we need to relink.
3528 procedure Choose_C_Plus_Plus_Link_Process;
3529 -- If the C++ compiler is not g++, create the correct script to link
3531 procedure Link_Foreign
3533 Main_Id : File_Name_Type;
3534 Source : Other_Source);
3535 -- Link a non-Ada main, when there is no Ada code
3537 ---------------------------------------
3538 -- Add_C_Plus_Plus_Link_For_Gnatmake --
3539 ---------------------------------------
3541 procedure Add_C_Plus_Plus_Link_For_Gnatmake is
3544 ("--LINK=" & Compiler_Names (C_Plus_Plus_Language_Index).all,
3546 end Add_C_Plus_Plus_Link_For_Gnatmake;
3548 -----------------------
3549 -- Check_Time_Stamps --
3550 -----------------------
3552 procedure Check_Time_Stamps (Exec_Time_Stamp : Time_Stamp_Type) is
3553 Prj_Data : Project_Data;
3556 for Prj in Project_Table.First ..
3557 Project_Table.Last (Project_Tree.Projects)
3559 Prj_Data := Project_Tree.Projects.Table (Prj);
3561 -- There is an archive only in project
3562 -- files with sources other than Ada
3565 if Data.Other_Sources_Present then
3567 Archive_Path : constant String := Get_Name_String
3568 (Prj_Data.Display_Object_Dir) & Directory_Separator
3569 & "lib" & Get_Name_String (Prj_Data.Display_Name)
3570 & '.' & Archive_Ext;
3571 Archive_TS : Time_Stamp_Type;
3574 Add_Str_To_Name_Buffer (Archive_Path);
3575 Archive_TS := File_Stamp (File_Name_Type'(Name_Find
));
3577 -- If the archive is later than the
3578 -- executable, we need to relink.
3580 if Archive_TS
/= Empty_Time_Stamp
3582 Exec_Time_Stamp
< Archive_TS
3584 Need_To_Relink
:= True;
3586 if Verbose_Mode
then
3588 Write_Str
(Archive_Path
);
3589 Write_Str
(" has time stamp ");
3590 Write_Str
("later than ");
3591 Write_Line
("executable");
3599 end Check_Time_Stamps
;
3601 -------------------------------------
3602 -- Choose_C_Plus_Plus_Link_Process --
3603 -------------------------------------
3605 procedure Choose_C_Plus_Plus_Link_Process
is
3607 if Compiler_Names
(C_Plus_Plus_Language_Index
) = null then
3608 Get_Compiler
(C_Plus_Plus_Language_Index
);
3610 end Choose_C_Plus_Plus_Link_Process
;
3616 procedure Link_Foreign
3618 Main_Id
: File_Name_Type
;
3619 Source
: Other_Source
)
3621 Executable_Name
: constant String :=
3624 (Project
=> Main_Project
,
3625 In_Tree
=> Project_Tree
,
3628 Ada_Main
=> False));
3629 -- File name of the executable
3631 Executable_Path
: constant String :=
3633 (Data
.Display_Exec_Dir
) &
3634 Directory_Separator
& Executable_Name
;
3635 -- Path name of the executable
3637 Exec_Time_Stamp
: Time_Stamp_Type
;
3640 -- Now, check if the executable is up to date. It is considered
3641 -- up to date if its time stamp is not earlier that the time stamp
3642 -- of any archive. Only do that if we don't know if we need to link.
3644 if not Need_To_Relink
then
3646 -- Get the time stamp of the executable
3649 Add_Str_To_Name_Buffer
(Executable_Path
);
3650 Exec_Time_Stamp
:= File_Stamp
(File_Name_Type
'(Name_Find));
3652 if Verbose_Mode then
3653 Write_Str (" Checking executable ");
3654 Write_Line (Executable_Name);
3657 -- If executable does not exist, we need to link
3659 if Exec_Time_Stamp = Empty_Time_Stamp then
3660 Need_To_Relink := True;
3662 if Verbose_Mode then
3663 Write_Line (" -> not found");
3666 -- Otherwise, get the time stamps of each archive. If one of
3667 -- them is found later than the executable, we need to relink.
3670 Check_Time_Stamps (Exec_Time_Stamp);
3673 -- If Need_To_Relink is False, we are done
3675 if Verbose_Mode and (not Need_To_Relink) then
3676 Write_Line (" -> up to date");
3682 if Need_To_Relink then
3687 -- Specify the executable path name
3689 Add_Argument (Dash_o, True);
3691 (Get_Name_String (Data.Display_Exec_Dir) &
3692 Directory_Separator &
3695 (Project => Main_Project,
3696 In_Tree => Project_Tree,
3699 Ada_Main => False)),
3702 -- Specify the object file of the main source
3705 (Object_Dir & Directory_Separator &
3706 Get_Name_String (Source.Object_Name),
3709 -- Add all the archives, in a correct order
3711 Add_Archives (For_Gnatmake => False);
3713 -- Add the switches specified in package Linker of
3714 -- the main project.
3719 Language => Source.Language,
3720 File_Name => Main_Id);
3722 -- Add the switches specified in attribute
3723 -- Linker_Options of packages Linker.
3725 if Link_Options_Switches = null then
3726 Link_Options_Switches :=
3728 (Linker_Options_Switches
(Main_Project
, Project_Tree
));
3731 Add_Arguments
(Link_Options_Switches
.all, True);
3733 -- Add the linking options specified on the
3736 for Arg
in 1 .. Linker_Options
.Last
loop
3737 Add_Argument
(Linker_Options
.Table
(Arg
), True);
3740 -- If there are shared libraries and the run path
3741 -- option is supported, add the run path switch.
3743 if Lib_Path
.Last
> 0 then
3746 String (Lib_Path
.Table
(1 .. Lib_Path
.Last
)),
3750 -- And invoke the linker
3752 Display_Command
(Linker_Name
.all, Linker_Path
);
3755 Arguments
(1 .. Last_Argument
),
3759 Report_Error
("could not link ", Main
);
3764 -- Start of processing of Link_Executables
3767 -- If no mains specified, get mains from attribute Main, if it exists
3769 if not Mains_Specified
then
3771 Element_Id
: String_List_Id
;
3772 Element
: String_Element
;
3775 Element_Id
:= Data
.Mains
;
3776 while Element_Id
/= Nil_String
loop
3777 Element
:= Project_Tree
.String_Elements
.Table
(Element_Id
);
3779 if Element
.Value
/= No_Name
then
3780 Mains
.Add_Main
(Get_Name_String
(Element
.Value
));
3783 Element_Id
:= Element
.Next
;
3788 if Mains
.Number_Of_Mains
= 0 then
3790 -- If the attribute Main is an empty list or not specified,
3791 -- there is nothing to do.
3793 if Verbose_Mode
then
3794 Write_Line
("No main to link");
3799 -- Check if -o was used for several mains
3801 if Output_File_Name
/= null and then Mains
.Number_Of_Mains
> 1 then
3802 Osint
.Fail
("cannot specify an executable name for several mains");
3805 -- Check how we are going to do the link
3807 if not Data
.Other_Sources_Present
then
3809 -- Only Ada sources in the main project, and even maybe not
3811 if Data
.Extends
= No_Project
and then
3812 not Data
.Langs
(Ada_Language_Index
)
3814 -- Fail if the main project has no source of any language
3818 Get_Name_String
(Data
.Name
),
3819 """ has no sources, so no main can be linked");
3822 -- Only Ada sources in the main project, call gnatmake directly
3826 -- Choose correct linker if there is C++ code in other projects
3828 if C_Plus_Plus_Is_Used
then
3829 Choose_C_Plus_Plus_Link_Process
;
3830 Add_Argument
(Dash_largs
, Verbose_Mode
);
3831 Add_C_Plus_Plus_Link_For_Gnatmake
;
3832 Add_Argument
(Dash_margs
, Verbose_Mode
);
3835 Compile_Link_With_Gnatmake
(Mains_Specified
);
3839 -- There are other language sources. First check if there are also
3842 if Data
.Langs
(Ada_Language_Index
) then
3844 -- There is a mix of Ada and other language sources in the main
3845 -- project. Any main that is not a source of the other languages
3846 -- will be deemed to be an Ada main.
3848 -- Find the mains of the other languages and the Ada mains
3851 Ada_Mains
.Set_Last
(0);
3852 Other_Mains
.Set_Last
(0);
3858 Main
: constant String := Mains
.Next_Main
;
3859 Main_Id
: File_Name_Type
;
3862 exit when Main
'Length = 0;
3864 -- Get the main file name
3867 Add_Str_To_Name_Buffer
(Main
);
3868 Canonical_Case_File_Name
(Name_Buffer
(1 .. Name_Len
));
3869 Main_Id
:= Name_Find
;
3871 -- Check if it is a source of a language other than Ada
3873 Source_Id
:= Data
.First_Other_Source
;
3874 while Source_Id
/= No_Other_Source
loop
3876 Project_Tree
.Other_Sources
.Table
(Source_Id
);
3877 exit when Source
.File_Name
= Main_Id
;
3878 Source_Id
:= Source
.Next
;
3881 -- If it is not, put it in the list of Ada mains
3883 if Source_Id
= No_Other_Source
then
3884 Ada_Mains
.Increment_Last
;
3885 Ada_Mains
.Table
(Ada_Mains
.Last
) := new String'(Main);
3887 -- Otherwise, put it in the list of other mains
3890 Other_Mains.Increment_Last;
3891 Other_Mains.Table (Other_Mains.Last) := Source;
3896 -- If C++ is one of the other language, create the shell script
3899 if C_Plus_Plus_Is_Used then
3900 Choose_C_Plus_Plus_Link_Process;
3903 -- Call gnatmake with the necessary switches for each non-Ada
3904 -- main, if there are some.
3906 for Main in 1 .. Other_Mains.Last loop
3908 Source : constant Other_Source := Other_Mains.Table (Main);
3913 -- Add -o if -o was specified
3915 if Output_File_Name = null then
3916 Add_Argument (Dash_o, True);
3920 (Project => Main_Project,
3921 In_Tree => Project_Tree,
3922 Main => Other_Mains.Table (Main).File_Name,
3924 Ada_Main => False)),
3928 -- Call gnatmake with the -B switch
3930 Add_Argument (Dash_B, True);
3932 -- Add to the linking options the object file of the source
3934 Add_Argument (Dash_largs, Verbose_Mode);
3936 (Get_Name_String (Source.Object_Name), Verbose_Mode);
3938 -- If C++ is one of the language, add the --LINK switch
3939 -- to the linking switches.
3941 if C_Plus_Plus_Is_Used then
3942 Add_C_Plus_Plus_Link_For_Gnatmake;
3945 -- Add -margs so that the following switches are for
3948 Add_Argument (Dash_margs, Verbose_Mode);
3950 -- And link with gnatmake
3952 Compile_Link_With_Gnatmake (Mains_Specified => False);
3956 -- If there are also Ada mains, call gnatmake for all these mains
3958 if Ada_Mains.Last /= 0 then
3961 -- Put all the Ada mains as the first arguments
3963 for Main in 1 .. Ada_Mains.Last loop
3964 Add_Argument (Ada_Mains.Table (Main).all, True);
3967 -- If C++ is one of the languages, add the --LINK switch to
3968 -- the linking switches.
3970 if Data.Langs (C_Plus_Plus_Language_Index) then
3971 Add_Argument (Dash_largs, Verbose_Mode);
3972 Add_C_Plus_Plus_Link_For_Gnatmake;
3973 Add_Argument (Dash_margs, Verbose_Mode);
3976 -- And link with gnatmake
3978 Compile_Link_With_Gnatmake (Mains_Specified => False);
3982 -- No Ada source in main project
3984 -- First, get the linker to invoke
3986 if Data.Langs (C_Plus_Plus_Language_Index) then
3987 Get_Compiler (C_Plus_Plus_Language_Index);
3988 Linker_Name := Compiler_Names (C_Plus_Plus_Language_Index);
3989 Linker_Path := Compiler_Paths (C_Plus_Plus_Language_Index);
3992 Get_Compiler (C_Language_Index);
3993 Linker_Name := Compiler_Names (C_Language_Index);
3994 Linker_Path := Compiler_Paths (C_Language_Index);
4001 -- Get each main, check if it is a source of the main project,
4002 -- and if it is, invoke the linker.
4006 Main : constant String := Mains.Next_Main;
4007 Main_Id : File_Name_Type;
4010 exit when Main'Length = 0;
4012 -- Get the file name of the main
4015 Add_Str_To_Name_Buffer (Main);
4016 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
4017 Main_Id := Name_Find;
4019 -- Check if it is a source of the main project file
4021 Source_Id := Data.First_Other_Source;
4022 while Source_Id /= No_Other_Source loop
4024 Project_Tree.Other_Sources.Table (Source_Id);
4025 exit when Source.File_Name = Main_Id;
4026 Source_Id := Source.Next;
4029 -- Report an error if it is not
4031 if Source_Id = No_Other_Source then
4033 (Main, "is not a source of project ",
4034 Get_Name_String (Data.Name));
4037 Link_Foreign (Main, Main_Id, Source);
4042 -- If no linking was done, report it, except in Quiet Output
4044 if (Verbose_Mode or (not Quiet_Output)) and (not Link_Done) then
4045 Osint.Write_Program_Name;
4047 if Mains.Number_Of_Mains = 1 then
4049 -- If there is only one executable, report its name too
4055 Main : constant String := Mains.Next_Main;
4056 Main_Id : File_Name_Type;
4059 Add_Str_To_Name_Buffer (Main);
4060 Main_Id := Name_Find;
4064 (Project => Main_Project,
4065 In_Tree => Project_Tree,
4068 Ada_Main => False)));
4069 Write_Line (""" up to date");
4073 Write_Line (": all executables up to date");
4078 end Link_Executables;
4084 procedure Report_Error
4090 -- If Keep_Going is True, output error message preceded by error header
4093 Total_Number_Of_Errors := Total_Number_Of_Errors + 1;
4094 Write_Str (Error_Header);
4100 -- Otherwise just fail
4103 Osint.Fail (S1, S2, S3);
4107 -------------------------
4108 -- Report_Total_Errors --
4109 -------------------------
4111 procedure Report_Total_Errors (Kind : String) is
4113 if Total_Number_Of_Errors /= 0 then
4114 if Total_Number_Of_Errors = 1 then
4116 ("One ", Kind, " error");
4120 ("Total of" & Total_Number_Of_Errors'Img,
4121 ' ' & Kind & " errors");
4124 end Report_Total_Errors;
4130 procedure Scan_Arg (Arg : String) is
4132 pragma Assert (Arg'First = 1);
4134 if Arg'Length = 0 then
4138 -- If preceding switch was -P, a project file name need to be
4139 -- specified, not a switch.
4141 if Project_File_Name_Expected then
4142 if Arg (1) = '-' then
4143 Osint.Fail ("project file name missing after -P");
4145 Project_File_Name_Expected := False;
4146 Project_File_Name := new String'(Arg
);
4149 -- If preceding switch was -o, an executable name need to be
4150 -- specified, not a switch.
4152 elsif Output_File_Name_Expected
then
4153 if Arg
(1) = '-' then
4154 Osint
.Fail
("output file name missing after -o");
4156 Output_File_Name_Expected
:= False;
4157 Output_File_Name
:= new String'(Arg);
4160 -- Set the processor/language for the following switches
4162 -- -cargs: Ada compiler arguments
4164 elsif Arg = "-cargs" then
4165 Current_Language := Ada_Language_Index;
4166 Current_Processor := Compiler;
4168 elsif Arg'Length > 7 and then Arg (1 .. 7) = "-cargs:" then
4170 Add_Str_To_Name_Buffer (Arg (8 .. Arg'Last));
4171 To_Lower (Name_Buffer (1 .. Name_Len));
4174 Lang : constant Name_Id := Name_Find;
4176 Current_Language := Language_Indexes.Get (Lang);
4178 if Current_Language = No_Language_Index then
4179 Add_Language_Name (Lang);
4180 Current_Language := Last_Language_Index;
4183 Current_Processor := Compiler;
4186 elsif Arg = "-largs" then
4187 Current_Processor := Linker;
4191 elsif Arg = "-gargs" then
4192 Current_Processor := None;
4194 -- A special test is needed for the -o switch within a -largs since
4195 -- that is another way to specify the name of the final executable.
4197 elsif Current_Processor = Linker and then Arg = "-o" then
4199 ("switch -o not allowed within a -largs. Use -o directly.");
4201 -- If current processor is not gprmake directly, store the option in
4202 -- the appropriate table.
4204 elsif Current_Processor /= None then
4207 -- Switches start with '-'
4209 elsif Arg (1) = '-' then
4210 if Arg'Length > 3 and then Arg (1 .. 3) = "-aP" then
4211 Add_Search_Project_Directory (Arg (4 .. Arg'Last));
4213 -- Record the switch, so that it is passed to gnatmake, if
4214 -- gnatmake is called.
4216 Saved_Switches.Append (new String'(Arg
));
4218 elsif Arg
= "-c" then
4219 Compile_Only
:= True;
4221 -- Make sure that when a main is specified and switch -c is used,
4222 -- only the main(s) is/are compiled.
4224 if Mains
.Number_Of_Mains
> 0 then
4225 Unique_Compile
:= True;
4228 elsif Arg
= "-d" then
4229 Display_Compilation_Progress
:= True;
4231 elsif Arg
= "-f" then
4232 Force_Compilations
:= True;
4234 elsif Arg
= "-h" then
4237 elsif Arg
= "-k" then
4240 elsif Arg
= "-o" then
4241 if Output_File_Name
/= null then
4242 Osint
.Fail
("cannot specify several -o switches");
4245 Output_File_Name_Expected
:= True;
4248 elsif Arg
'Length >= 2 and then Arg
(2) = 'P' then
4249 if Project_File_Name
/= null then
4250 Osint
.Fail
("cannot have several project files specified");
4252 elsif Arg
'Length = 2 then
4253 Project_File_Name_Expected
:= True;
4256 Project_File_Name
:= new String'(Arg (3 .. Arg'Last));
4259 elsif Arg = "-p" or else Arg = "--create-missing-dirs" then
4260 Setup_Projects := True;
4262 elsif Arg = "-q" then
4263 Quiet_Output := True;
4265 elsif Arg = "-u" then
4266 Unique_Compile := True;
4267 Compile_Only := True;
4269 elsif Arg = "-v" then
4270 Verbose_Mode := True;
4273 elsif Arg'Length = 4 and then Arg (1 .. 3) = "-vP"
4274 and then Arg (4) in '0' .. '2'
4278 Current_Verbosity := Prj.Default;
4280 Current_Verbosity := Prj.Medium;
4282 Current_Verbosity := Prj.High;
4287 elsif Arg'Length >= 3 and then Arg (2) = 'X
'
4288 and then Is_External_Assignment (Arg)
4290 -- Is_External_Assignment has side effects when it returns True
4292 -- Record the -X switch, so that it will be passed to gnatmake,
4293 -- if gnatmake is called.
4295 Saved_Switches.Append (new String'(Arg
));
4298 Osint
.Fail
("illegal option """, Arg
, """");
4302 -- Not a switch: must be a main
4304 Mains
.Add_Main
(Arg
);
4306 -- Make sure that when a main is specified and switch -c is used,
4307 -- only the main(s) is/are compiled.
4309 if Compile_Only
then
4310 Unique_Compile
:= True;
4319 function Strip_CR_LF
(Text
: String) return String is
4320 To
: String (1 .. Text
'Length);
4321 Index_To
: Natural := 0;
4324 for Index
in Text
'Range loop
4325 if (Text
(Index
) /= ASCII
.CR
) and then (Text
(Index
) /= ASCII
.LF
) then
4326 Index_To
:= Index_To
+ 1;
4327 To
(Index_To
) := Text
(Index
);
4331 return To
(1 .. Index_To
);
4340 if not Usage_Output
then
4341 Usage_Output
:= True;
4344 Write_Str
("Usage: ");
4345 Osint
.Write_Program_Name
;
4346 Write_Str
(" -P<project file> [opts] [name] {");
4347 Write_Str
("[-cargs:lang opts] ");
4348 Write_Str
("[-largs opts] [-gargs opts]}");
4351 Write_Str
(" name is zero or more file names");
4357 Write_Str
("gprmake switches:");
4362 Write_Str
(" -aPdir Add directory dir to project search path");
4367 Write_Str
(" -c Compile only");
4372 Write_Str
(" -f Force recompilations");
4377 Write_Str
(" -k Keep going after compilation errors");
4382 Write_Str
(" -o name Choose an alternate executable name");
4387 Write_Str
(" -p Create missing obj, lib and exec dirs");
4392 Write_Str
(" -Pproj Use GNAT Project File proj");
4397 Write_Str
(" -q Be quiet/terse");
4403 (" -u Unique compilation. Only compile the given files");
4408 Write_Str
(" -v Verbose output");
4413 Write_Str
(" -vPx Specify verbosity when parsing Project Files");
4418 Write_Str
(" -Xnm=val Specify an external reference for " &
4425 Write_Line
(" -cargs opts opts are passed to the Ada compiler");
4427 -- Line for -cargs:lang
4429 Write_Line
(" -cargs:<lang> opts");
4430 Write_Line
(" opts are passed to the compiler " &
4431 "for language < lang > ");
4435 Write_Str
(" -largs opts opts are passed to the linker");
4440 Write_Str
(" -gargs opts opts directly interpreted by gprmake");
4448 Makeutl
.Do_Fail
:= Report_Error
'Access;