1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2006-2015, 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 ------------------------------------------------------------------------------
26 with Makeutl
; use Makeutl
;
29 with Output
; use Output
;
34 with Prj
.Proc
; use Prj
.Proc
;
35 with Prj
.Tree
; use Prj
.Tree
;
36 with Prj
.Util
; use Prj
.Util
;
38 with Snames
; use Snames
;
40 with Ada
.Directories
; use Ada
.Directories
;
41 with Ada
.Exceptions
; use Ada
.Exceptions
;
43 with GNAT
.Case_Util
; use GNAT
.Case_Util
;
44 with GNAT
.HTable
; use GNAT
.HTable
;
46 package body Prj
.Conf
is
48 Auto_Cgpr
: constant String := "auto.cgpr";
50 Config_Project_Env_Var
: constant String := "GPR_CONFIG";
51 -- Name of the environment variable that provides the name of the
52 -- configuration file to use.
54 Gprconfig_Name
: constant String := "gprconfig";
56 Warn_For_RTS
: Boolean := True;
57 -- Set to False when gprbuild parse again the project files, to avoid
58 -- an incorrect warning.
60 type Runtime_Root_Data
;
61 type Runtime_Root_Ptr
is access Runtime_Root_Data
;
62 type Runtime_Root_Data
is record
64 Next
: Runtime_Root_Ptr
;
66 -- Data for a runtime root to be used when adding directories to the
69 type Compiler_Root_Data
;
70 type Compiler_Root_Ptr
is access Compiler_Root_Data
;
71 type Compiler_Root_Data
is record
73 Runtimes
: Runtime_Root_Ptr
;
74 Next
: Compiler_Root_Ptr
;
76 -- Data for a compiler root to be used when adding directories to the
79 First_Compiler_Root
: Compiler_Root_Ptr
:= null;
80 -- Head of the list of compiler roots
82 package RTS_Languages
is new GNAT
.HTable
.Simple_HTable
83 (Header_Num
=> Prj
.Header_Num
,
85 No_Element
=> No_Name
,
89 -- Stores the runtime names for the various languages. This is in general
90 -- set from a --RTS command line option.
92 -----------------------
93 -- Local_Subprograms --
94 -----------------------
97 (Config_File
: Prj
.Project_Id
;
98 Autoconf_Specified
: Boolean;
99 Project_Tree
: Prj
.Project_Tree_Ref
;
100 Target
: String := "") return Boolean;
101 -- Check that the config file's target matches Target.
102 -- Target should be set to the empty string when the user did not specify
103 -- a target. If the target in the configuration file is invalid, this
104 -- function will raise Invalid_Config with an appropriate message.
105 -- Autoconf_Specified should be set to True if the user has used
108 function Locate_Config_File
(Name
: String) return String_Access
;
109 -- Search for Name in the config files directory. Return full path if
110 -- found, or null otherwise.
112 procedure Raise_Invalid_Config
(Msg
: String);
113 pragma No_Return
(Raise_Invalid_Config
);
114 -- Raises exception Invalid_Config with given message
116 procedure Apply_Config_File
117 (Config_File
: Prj
.Project_Id
;
118 Project_Tree
: Prj
.Project_Tree_Ref
);
119 -- Apply the configuration file settings to all the projects in the
120 -- project tree. The Project_Tree must have been parsed first, and
121 -- processed through the first phase so that all its projects are known.
123 -- Currently, this will add new attributes and packages in the various
124 -- projects, so that when the second phase of the processing is performed
125 -- these attributes are automatically taken into account.
127 type State
is (No_State
);
129 procedure Look_For_Project_Paths
130 (Project
: Project_Id
;
131 Tree
: Project_Tree_Ref
;
132 With_State
: in out State
);
133 -- Check the compilers in the Project and add record them in the list
134 -- rooted at First_Compiler_Root, with their runtimes, if they are not
135 -- already in the list.
137 procedure Update_Project_Path
is new
138 For_Every_Project_Imported
140 Action
=> Look_For_Project_Paths
);
142 ------------------------------------
143 -- Add_Default_GNAT_Naming_Scheme --
144 ------------------------------------
146 procedure Add_Default_GNAT_Naming_Scheme
147 (Config_File
: in out Project_Node_Id
;
148 Project_Tree
: Project_Node_Tree_Ref
)
150 procedure Create_Attribute
153 Index
: String := "";
154 Pkg
: Project_Node_Id
:= Empty_Node
);
156 ----------------------
157 -- Create_Attribute --
158 ----------------------
160 procedure Create_Attribute
163 Index
: String := "";
164 Pkg
: Project_Node_Id
:= Empty_Node
)
166 Attr
: Project_Node_Id
;
167 pragma Unreferenced
(Attr
);
169 Expr
: Name_Id
:= No_Name
;
170 Val
: Name_Id
:= No_Name
;
171 Parent
: Project_Node_Id
:= Config_File
;
175 Name_Len
:= Index
'Length;
176 Name_Buffer
(1 .. Name_Len
) := Index
;
180 if Pkg
/= Empty_Node
then
184 Name_Len
:= Value
'Length;
185 Name_Buffer
(1 .. Name_Len
) := Value
;
188 Attr
:= Create_Attribute
189 (Tree
=> Project_Tree
,
190 Prj_Or_Pkg
=> Parent
,
194 Value
=> Create_Literal_String
(Expr
, Project_Tree
));
195 end Create_Attribute
;
200 Naming
: Project_Node_Id
;
201 Compiler
: Project_Node_Id
;
203 -- Start of processing for Add_Default_GNAT_Naming_Scheme
206 if Config_File
= Empty_Node
then
208 -- Create a dummy config file if none was found
210 Name_Len
:= Auto_Cgpr
'Length;
211 Name_Buffer
(1 .. Name_Len
) := Auto_Cgpr
;
214 -- An invalid project name to avoid conflicts with user-created ones
217 Name_Buffer
(1 .. Name_Len
) := "_auto";
221 (In_Tree
=> Project_Tree
,
223 Full_Path
=> Path_Name_Type
(Name
),
224 Is_Config_File
=> True);
226 -- Setup library support
228 case MLib
.Tgt
.Support_For_Libraries
is
233 Create_Attribute
(Name_Library_Support
, "static_only");
236 Create_Attribute
(Name_Library_Support
, "full");
239 if MLib
.Tgt
.Standalone_Library_Auto_Init_Is_Supported
then
240 Create_Attribute
(Name_Library_Auto_Init_Supported
, "true");
242 Create_Attribute
(Name_Library_Auto_Init_Supported
, "false");
245 -- Declare an empty target
247 Create_Attribute
(Name_Target
, "");
249 -- Setup Ada support (Ada is the default language here, since this
250 -- is only called when no config file existed initially, ie for
253 Create_Attribute
(Name_Default_Language
, "ada");
255 Compiler
:= Create_Package
(Project_Tree
, Config_File
, "compiler");
257 (Name_Driver
, "gcc", "ada", Pkg
=> Compiler
);
259 (Name_Language_Kind
, "unit_based", "ada", Pkg
=> Compiler
);
261 (Name_Dependency_Kind
, "ALI_File", "ada", Pkg
=> Compiler
);
263 Naming
:= Create_Package
(Project_Tree
, Config_File
, "naming");
264 Create_Attribute
(Name_Spec_Suffix
, ".ads", "ada", Pkg
=> Naming
);
265 Create_Attribute
(Name_Separate_Suffix
, ".adb", "ada", Pkg
=> Naming
);
266 Create_Attribute
(Name_Body_Suffix
, ".adb", "ada", Pkg
=> Naming
);
267 Create_Attribute
(Name_Dot_Replacement
, "-", Pkg
=> Naming
);
268 Create_Attribute
(Name_Casing
, "lowercase", Pkg
=> Naming
);
270 if Current_Verbosity
= High
then
271 Write_Line
("Automatically generated (in-memory) config file");
273 (Project
=> Config_File
,
274 In_Tree
=> Project_Tree
,
275 Backward_Compatibility
=> False);
278 end Add_Default_GNAT_Naming_Scheme
;
280 -----------------------
281 -- Apply_Config_File --
282 -----------------------
284 procedure Apply_Config_File
285 (Config_File
: Prj
.Project_Id
;
286 Project_Tree
: Prj
.Project_Tree_Ref
)
288 procedure Add_Attributes
289 (Project_Tree
: Project_Tree_Ref
;
290 Conf_Decl
: Declarations
;
291 User_Decl
: in out Declarations
);
292 -- Process the attributes in the config declarations. For
293 -- single string values, if the attribute is not declared in
294 -- the user declarations, declare it with the value in the
295 -- config declarations. For string list values, prepend the
296 -- value in the user declarations with the value in the config
303 procedure Add_Attributes
304 (Project_Tree
: Project_Tree_Ref
;
305 Conf_Decl
: Declarations
;
306 User_Decl
: in out Declarations
)
308 Shared
: constant Shared_Project_Tree_Data_Access
:=
310 Conf_Attr_Id
: Variable_Id
;
311 Conf_Attr
: Variable
;
312 Conf_Array_Id
: Array_Id
;
313 Conf_Array
: Array_Data
;
314 Conf_Array_Elem_Id
: Array_Element_Id
;
315 Conf_Array_Elem
: Array_Element
;
316 Conf_List
: String_List_Id
;
317 Conf_List_Elem
: String_Element
;
319 User_Attr_Id
: Variable_Id
;
320 User_Attr
: Variable
;
321 User_Array_Id
: Array_Id
;
322 User_Array
: Array_Data
;
323 User_Array_Elem_Id
: Array_Element_Id
;
324 User_Array_Elem
: Array_Element
;
327 Conf_Attr_Id
:= Conf_Decl
.Attributes
;
328 User_Attr_Id
:= User_Decl
.Attributes
;
330 while Conf_Attr_Id
/= No_Variable
loop
331 Conf_Attr
:= Shared
.Variable_Elements
.Table
(Conf_Attr_Id
);
332 User_Attr
:= Shared
.Variable_Elements
.Table
(User_Attr_Id
);
334 if not Conf_Attr
.Value
.Default
then
335 if User_Attr
.Value
.Default
then
337 -- No attribute declared in user project file: just copy
338 -- the value of the configuration attribute.
340 User_Attr
.Value
:= Conf_Attr
.Value
;
341 Shared
.Variable_Elements
.Table
(User_Attr_Id
) := User_Attr
;
343 elsif User_Attr
.Value
.Kind
= List
344 and then Conf_Attr
.Value
.Values
/= Nil_String
346 -- List attribute declared in both the user project and the
347 -- configuration project: prepend the user list with the
348 -- configuration list.
351 User_List
: constant String_List_Id
:=
352 User_Attr
.Value
.Values
;
353 Conf_List
: String_List_Id
:= Conf_Attr
.Value
.Values
;
354 Conf_Elem
: String_Element
;
355 New_List
: String_List_Id
;
356 New_Elem
: String_Element
;
361 String_Element_Table
.Increment_Last
362 (Shared
.String_Elements
);
364 String_Element_Table
.Last
(Shared
.String_Elements
);
366 -- Value of attribute is new list
368 User_Attr
.Value
.Values
:= New_List
;
369 Shared
.Variable_Elements
.Table
(User_Attr_Id
) :=
373 -- Get each element of configuration list
375 Conf_Elem
:= Shared
.String_Elements
.Table
(Conf_List
);
376 New_Elem
:= Conf_Elem
;
377 Conf_List
:= Conf_Elem
.Next
;
379 if Conf_List
= Nil_String
then
381 -- If it is the last element in the list, connect
382 -- to first element of user list, and we are done.
384 New_Elem
.Next
:= User_List
;
385 Shared
.String_Elements
.Table
(New_List
) := New_Elem
;
389 -- If it is not the last element in the list, add
392 String_Element_Table
.Increment_Last
393 (Shared
.String_Elements
);
394 New_Elem
.Next
:= String_Element_Table
.Last
395 (Shared
.String_Elements
);
396 Shared
.String_Elements
.Table
(New_List
) := New_Elem
;
397 New_List
:= New_Elem
.Next
;
404 Conf_Attr_Id
:= Conf_Attr
.Next
;
405 User_Attr_Id
:= User_Attr
.Next
;
408 Conf_Array_Id
:= Conf_Decl
.Arrays
;
409 while Conf_Array_Id
/= No_Array
loop
410 Conf_Array
:= Shared
.Arrays
.Table
(Conf_Array_Id
);
412 User_Array_Id
:= User_Decl
.Arrays
;
413 while User_Array_Id
/= No_Array
loop
414 User_Array
:= Shared
.Arrays
.Table
(User_Array_Id
);
415 exit when User_Array
.Name
= Conf_Array
.Name
;
416 User_Array_Id
:= User_Array
.Next
;
419 -- If this associative array does not exist in the user project
420 -- file, do a shallow copy of the full associative array.
422 if User_Array_Id
= No_Array
then
423 Array_Table
.Increment_Last
(Shared
.Arrays
);
424 User_Array
:= Conf_Array
;
425 User_Array
.Next
:= User_Decl
.Arrays
;
426 User_Decl
.Arrays
:= Array_Table
.Last
(Shared
.Arrays
);
427 Shared
.Arrays
.Table
(User_Decl
.Arrays
) := User_Array
;
429 -- Otherwise, check each array element
432 Conf_Array_Elem_Id
:= Conf_Array
.Value
;
433 while Conf_Array_Elem_Id
/= No_Array_Element
loop
435 Shared
.Array_Elements
.Table
(Conf_Array_Elem_Id
);
437 User_Array_Elem_Id
:= User_Array
.Value
;
438 while User_Array_Elem_Id
/= No_Array_Element
loop
440 Shared
.Array_Elements
.Table
(User_Array_Elem_Id
);
441 exit when User_Array_Elem
.Index
= Conf_Array_Elem
.Index
;
442 User_Array_Elem_Id
:= User_Array_Elem
.Next
;
445 -- If the array element doesn't exist in the user array,
446 -- insert a shallow copy of the conf array element in the
449 if User_Array_Elem_Id
= No_Array_Element
then
450 Array_Element_Table
.Increment_Last
451 (Shared
.Array_Elements
);
452 User_Array_Elem
:= Conf_Array_Elem
;
453 User_Array_Elem
.Next
:= User_Array
.Value
;
455 Array_Element_Table
.Last
(Shared
.Array_Elements
);
456 Shared
.Array_Elements
.Table
(User_Array
.Value
) :=
458 Shared
.Arrays
.Table
(User_Array_Id
) := User_Array
;
460 -- Otherwise, if the value is a string list, prepend the
461 -- conf array element value to the array element.
463 elsif Conf_Array_Elem
.Value
.Kind
= List
then
464 Conf_List
:= Conf_Array_Elem
.Value
.Values
;
466 if Conf_List
/= Nil_String
then
468 Link
: constant String_List_Id
:=
469 User_Array_Elem
.Value
.Values
;
470 Previous
: String_List_Id
:= Nil_String
;
471 Next
: String_List_Id
;
476 Shared
.String_Elements
.Table
(Conf_List
);
477 String_Element_Table
.Increment_Last
478 (Shared
.String_Elements
);
480 String_Element_Table
.Last
481 (Shared
.String_Elements
);
482 Shared
.String_Elements
.Table
(Next
) :=
485 if Previous
= Nil_String
then
486 User_Array_Elem
.Value
.Values
:= Next
;
487 Shared
.Array_Elements
.Table
488 (User_Array_Elem_Id
) := User_Array_Elem
;
491 Shared
.String_Elements
.Table
492 (Previous
).Next
:= Next
;
497 Conf_List
:= Conf_List_Elem
.Next
;
499 if Conf_List
= Nil_String
then
500 Shared
.String_Elements
.Table
501 (Previous
).Next
:= Link
;
509 Conf_Array_Elem_Id
:= Conf_Array_Elem
.Next
;
513 Conf_Array_Id
:= Conf_Array
.Next
;
517 Shared
: constant Shared_Project_Tree_Data_Access
:= Project_Tree
.Shared
;
519 Conf_Decl
: constant Declarations
:= Config_File
.Decl
;
520 Conf_Pack_Id
: Package_Id
;
521 Conf_Pack
: Package_Element
;
523 User_Decl
: Declarations
;
524 User_Pack_Id
: Package_Id
;
525 User_Pack
: Package_Element
;
529 Debug_Output
("Applying config file to a project tree");
531 Proj
:= Project_Tree
.Projects
;
532 while Proj
/= null loop
533 if Proj
.Project
/= Config_File
then
534 User_Decl
:= Proj
.Project
.Decl
;
536 (Project_Tree
=> Project_Tree
,
537 Conf_Decl
=> Conf_Decl
,
538 User_Decl
=> User_Decl
);
540 Conf_Pack_Id
:= Conf_Decl
.Packages
;
541 while Conf_Pack_Id
/= No_Package
loop
542 Conf_Pack
:= Shared
.Packages
.Table
(Conf_Pack_Id
);
544 User_Pack_Id
:= User_Decl
.Packages
;
545 while User_Pack_Id
/= No_Package
loop
546 User_Pack
:= Shared
.Packages
.Table
(User_Pack_Id
);
547 exit when User_Pack
.Name
= Conf_Pack
.Name
;
548 User_Pack_Id
:= User_Pack
.Next
;
551 if User_Pack_Id
= No_Package
then
552 Package_Table
.Increment_Last
(Shared
.Packages
);
553 User_Pack
:= Conf_Pack
;
554 User_Pack
.Next
:= User_Decl
.Packages
;
555 User_Decl
.Packages
:= Package_Table
.Last
(Shared
.Packages
);
556 Shared
.Packages
.Table
(User_Decl
.Packages
) := User_Pack
;
560 (Project_Tree
=> Project_Tree
,
561 Conf_Decl
=> Conf_Pack
.Decl
,
562 User_Decl
=> Shared
.Packages
.Table
563 (User_Pack_Id
).Decl
);
566 Conf_Pack_Id
:= Conf_Pack
.Next
;
569 Proj
.Project
.Decl
:= User_Decl
;
571 -- For aggregate projects, we need to apply the config to all
572 -- their aggregated trees as well.
574 if Proj
.Project
.Qualifier
in Aggregate_Project
then
576 List
: Aggregated_Project_List
;
578 List
:= Proj
.Project
.Aggregated_Projects
;
579 while List
/= null loop
581 ("Recursively apply config to aggregated tree",
584 (Config_File
, Project_Tree
=> List
.Tree
);
593 end Apply_Config_File
;
599 function Check_Target
600 (Config_File
: Project_Id
;
601 Autoconf_Specified
: Boolean;
602 Project_Tree
: Prj
.Project_Tree_Ref
;
603 Target
: String := "") return Boolean
605 Shared
: constant Shared_Project_Tree_Data_Access
:=
607 Variable
: constant Variable_Value
:=
609 (Name_Target
, Config_File
.Decl
.Attributes
, Shared
);
610 Tgt_Name
: Name_Id
:= No_Name
;
614 if Variable
/= Nil_Variable_Value
and then not Variable
.Default
then
615 Tgt_Name
:= Variable
.Value
;
622 and then (Length_Of_Name
(Tgt_Name
) = 0
623 or else Target
= Get_Name_String
(Tgt_Name
)));
626 if Autoconf_Specified
then
628 Write_Line
("inconsistent targets, performing autoconf");
634 if Tgt_Name
/= No_Name
then
636 ("mismatched targets: """
637 & Get_Name_String
(Tgt_Name
) & """ in configuration, """
638 & Target
& """ specified");
641 ("no target specified in configuration file");
649 --------------------------------------
650 -- Get_Or_Create_Configuration_File --
651 --------------------------------------
653 procedure Get_Or_Create_Configuration_File
654 (Project
: Project_Id
;
655 Conf_Project
: Project_Id
;
656 Project_Tree
: Project_Tree_Ref
;
657 Project_Node_Tree
: Prj
.Tree
.Project_Node_Tree_Ref
;
658 Env
: in out Prj
.Tree
.Environment
;
659 Allow_Automatic_Generation
: Boolean;
660 Config_File_Name
: String := "";
661 Autoconf_Specified
: Boolean;
662 Target_Name
: String := "";
663 Normalized_Hostname
: String;
664 Packages_To_Check
: String_List_Access
:= null;
665 Config
: out Prj
.Project_Id
;
666 Config_File_Path
: out String_Access
;
667 Automatically_Generated
: out Boolean;
668 On_Load_Config
: Config_File_Hook
:= null)
670 Shared
: constant Shared_Project_Tree_Data_Access
:= Project_Tree
.Shared
;
672 At_Least_One_Compiler_Command
: Boolean := False;
673 -- Set to True if at least one attribute Ide'Compiler_Command is
674 -- specified for one language of the system.
676 Conf_File_Name
: String_Access
:= new String'(Config_File_Name);
677 -- The configuration project file name. May be modified if there are
678 -- switches --config= in the Builder package of the main project.
680 Selected_Target : String_Access := new String'(Target_Name
);
682 function Default_File_Name
return String;
683 -- Return the name of the default config file that should be tested
685 procedure Do_Autoconf
;
686 -- Generate a new config file through gprconfig. In case of error, this
687 -- raises the Invalid_Config exception with an appropriate message
689 procedure Check_Builder_Switches
;
690 -- Check for switches --config and --RTS in package Builder
692 procedure Get_Project_Target
;
693 -- If Target_Name is empty, get the specified target in the project
696 procedure Get_Project_Runtimes
;
697 -- Get the various Runtime (<lang>) in the project file or any project
698 -- it extends, if any are specified.
700 function Get_Config_Switches
return Argument_List_Access
;
701 -- Return the --config switches to use for gprconfig
703 function Get_Db_Switches
return Argument_List_Access
;
704 -- Return the --db switches to use for gprconfig
706 function Might_Have_Sources
(Project
: Project_Id
) return Boolean;
707 -- True if the specified project might have sources (ie the user has not
708 -- explicitly specified it. We haven't checked the file system, nor do
709 -- we need to at this stage.
711 ----------------------------
712 -- Check_Builder_Switches --
713 ----------------------------
715 procedure Check_Builder_Switches
is
716 Get_RTS_Switches
: constant Boolean :=
717 RTS_Languages
.Get_First
= No_Name
;
718 -- If no switch --RTS have been specified on the command line, look
719 -- for --RTS switches in the Builder switches.
721 Builder
: constant Package_Id
:=
722 Value_Of
(Name_Builder
, Project
.Decl
.Packages
, Shared
);
724 Switch_Array_Id
: Array_Element_Id
;
725 -- The Switches to be checked
727 procedure Check_Switches
;
728 -- Check the switches in Switch_Array_Id
734 procedure Check_Switches
is
735 Switch_Array
: Array_Element
;
736 Switch_List
: String_List_Id
:= Nil_String
;
737 Switch
: String_Element
;
739 Lang_Last
: Positive;
742 while Switch_Array_Id
/= No_Array_Element
loop
744 Shared
.Array_Elements
.Table
(Switch_Array_Id
);
746 Switch_List
:= Switch_Array
.Value
.Values
;
747 List_Loop
: while Switch_List
/= Nil_String
loop
748 Switch
:= Shared
.String_Elements
.Table
(Switch_List
);
750 if Switch
.Value
/= No_Name
then
751 Get_Name_String
(Switch
.Value
);
753 if Conf_File_Name
'Length = 0
754 and then Name_Len
> 9
755 and then Name_Buffer
(1 .. 9) = "--config="
758 new String'(Name_Buffer (10 .. Name_Len));
760 elsif Get_RTS_Switches
761 and then Name_Len >= 7
762 and then Name_Buffer (1 .. 5) = "--RTS"
764 if Name_Buffer (6) = '=' then
765 if not Runtime_Name_Set_For (Name_Ada) then
768 Name_Buffer (7 .. Name_Len));
772 and then Name_Buffer (6) = ':'
773 and then Name_Buffer (7) /= '='
776 while Lang_Last < Name_Len
777 and then Name_Buffer (Lang_Last + 1) /= '='
779 Lang_Last := Lang_Last + 1;
782 if Name_Buffer (Lang_Last + 1) = '=' then
784 RTS : constant String :=
785 Name_Buffer (Lang_Last + 2 .. Name_Len);
787 Name_Buffer (1 .. Lang_Last - 6) :=
788 Name_Buffer (7 .. Lang_Last);
789 Name_Len := Lang_Last - 6;
790 To_Lower (Name_Buffer (1 .. Name_Len));
793 if not Runtime_Name_Set_For (Lang) then
794 Set_Runtime_For (Lang, RTS);
802 Switch_List := Switch.Next;
805 Switch_Array_Id := Switch_Array.Next;
809 -- Start of processing for Check_Builder_Switches
812 if Builder /= No_Package then
815 (Name => Name_Switches,
816 In_Arrays => Shared.Packages.Table (Builder).Decl.Arrays,
822 (Name => Name_Default_Switches,
823 In_Arrays => Shared.Packages.Table (Builder).Decl.Arrays,
827 end Check_Builder_Switches;
829 ------------------------
830 -- Get_Project_Target --
831 ------------------------
833 procedure Get_Project_Target is
835 if Selected_Target'Length = 0 then
837 -- Check if attribute Target is specified in the main
838 -- project, or in a project it extends. If it is, use this
839 -- target to invoke gprconfig.
842 Variable : Variable_Value;
844 Tgt_Name : Name_Id := No_Name;
849 while Proj /= No_Project loop
851 Value_Of (Name_Target, Proj.Decl.Attributes, Shared);
853 if Variable /= Nil_Variable_Value
854 and then not Variable.Default
855 and then Variable.Value /= No_Name
857 Tgt_Name := Variable.Value;
861 Proj := Proj.Extends;
862 end loop Project_Loop;
864 if Tgt_Name /= No_Name then
865 Selected_Target := new String'(Get_Name_String
(Tgt_Name
));
869 end Get_Project_Target
;
871 --------------------------
872 -- Get_Project_Runtimes --
873 --------------------------
875 procedure Get_Project_Runtimes
is
876 Element
: Array_Element
;
877 Id
: Array_Element_Id
;
883 while Proj
/= No_Project
loop
884 Id
:= Value_Of
(Name_Runtime
, Proj
.Decl
.Arrays
, Shared
);
885 while Id
/= No_Array_Element
loop
886 Element
:= Shared
.Array_Elements
.Table
(Id
);
887 Lang
:= Element
.Index
;
889 if not Runtime_Name_Set_For
(Lang
) then
891 (Lang
, RTS_Name
=> Get_Name_String
(Element
.Value
.Value
));
897 Proj
:= Proj
.Extends
;
899 end Get_Project_Runtimes
;
901 -----------------------
902 -- Default_File_Name --
903 -----------------------
905 function Default_File_Name
return String is
906 Ada_RTS
: constant String := Runtime_Name_For
(Name_Ada
);
910 if Selected_Target
'Length /= 0 then
911 if Ada_RTS
/= "" then
913 Selected_Target
.all & '-' &
914 Ada_RTS
& Config_Project_File_Extension
;
917 Selected_Target
.all & Config_Project_File_Extension
;
920 elsif Ada_RTS
/= "" then
921 return Ada_RTS
& Config_Project_File_Extension
;
924 Tmp
:= Getenv
(Config_Project_Env_Var
);
927 T
: constant String := Tmp
.all;
933 return Default_Config_Name
;
939 end Default_File_Name
;
945 procedure Do_Autoconf
is
946 Obj_Dir
: constant Variable_Value
:=
949 Conf_Project
.Decl
.Attributes
,
952 Gprconfig_Path
: String_Access
;
956 Gprconfig_Path
:= Locate_Exec_On_Path
(Gprconfig_Name
);
958 if Gprconfig_Path
= null then
960 ("could not locate gprconfig for auto-configuration");
963 -- First, find the object directory of the Conf_Project
965 -- If the object directory is a relative one and Build_Tree_Dir is
966 -- set, first add it.
970 if Obj_Dir
= Nil_Variable_Value
or else Obj_Dir
.Default
then
972 if Build_Tree_Dir
/= null then
973 Add_Str_To_Name_Buffer
(Build_Tree_Dir
.all);
975 if Get_Name_String
(Conf_Project
.Directory
.Display_Name
)'Length
979 ("cannot relocate deeper than object directory");
982 Add_Str_To_Name_Buffer
984 (Get_Name_String
(Conf_Project
.Directory
.Display_Name
),
987 Get_Name_String
(Conf_Project
.Directory
.Display_Name
);
991 if Is_Absolute_Path
(Get_Name_String
(Obj_Dir
.Value
)) then
992 Get_Name_String
(Obj_Dir
.Value
);
995 if Build_Tree_Dir
/= null then
997 (Conf_Project
.Directory
.Display_Name
)'Length <
1000 Raise_Invalid_Config
1001 ("cannot relocate deeper than object directory");
1004 Add_Str_To_Name_Buffer
(Build_Tree_Dir
.all);
1005 Add_Str_To_Name_Buffer
1007 (Get_Name_String
(Conf_Project
.Directory
.Display_Name
),
1010 Add_Str_To_Name_Buffer
1011 (Get_Name_String
(Conf_Project
.Directory
.Display_Name
));
1014 Add_Str_To_Name_Buffer
(Get_Name_String
(Obj_Dir
.Value
));
1018 if Subdirs
/= null then
1019 Add_Char_To_Name_Buffer
(Directory_Separator
);
1020 Add_Str_To_Name_Buffer
(Subdirs
.all);
1023 for J
in 1 .. Name_Len
loop
1024 if Name_Buffer
(J
) = '/' then
1025 Name_Buffer
(J
) := Directory_Separator
;
1029 -- Make sure that Obj_Dir ends with a directory separator
1031 if Name_Buffer
(Name_Len
) /= Directory_Separator
then
1032 Name_Len
:= Name_Len
+ 1;
1033 Name_Buffer
(Name_Len
) := Directory_Separator
;
1037 Obj_Dir
: constant String := Name_Buffer
(1 .. Name_Len
);
1038 Config_Switches
: Argument_List_Access
;
1039 Db_Switches
: Argument_List_Access
;
1040 Args
: Argument_List
(1 .. 5);
1041 Arg_Last
: Positive;
1042 Obj_Dir_Exists
: Boolean := True;
1045 -- Check if the object directory exists. If Setup_Projects is True
1046 -- (-p) and directory does not exist, attempt to create it.
1047 -- Otherwise, if directory does not exist, fail without calling
1050 if not Is_Directory
(Obj_Dir
)
1051 and then (Setup_Projects
or else Subdirs
/= null)
1054 Create_Path
(Obj_Dir
);
1056 if not Quiet_Output
then
1057 Write_Str
("object directory """);
1058 Write_Str
(Obj_Dir
);
1059 Write_Line
(""" created");
1064 Raise_Invalid_Config
1065 ("could not create object directory " & Obj_Dir
);
1069 if not Is_Directory
(Obj_Dir
) then
1070 case Env
.Flags
.Require_Obj_Dirs
is
1072 Raise_Invalid_Config
1073 ("object directory " & Obj_Dir
& " does not exist");
1078 "?object directory " & Obj_Dir
& " does not exist");
1079 Obj_Dir_Exists
:= False;
1086 -- Get the config switches. This should be done only now, as some
1087 -- runtimes may have been found in the Builder switches.
1089 Config_Switches
:= Get_Config_Switches
;
1091 -- Get eventual --db switches
1093 Db_Switches
:= Get_Db_Switches
;
1097 Args
(1) := new String'("--batch");
1098 Args (2) := new String'("-o");
1100 -- If no config file was specified, set the auto.cgpr one
1102 if Conf_File_Name
'Length = 0 then
1103 if Obj_Dir_Exists
then
1104 Args
(3) := new String'(Obj_Dir & Auto_Cgpr);
1108 Path_FD : File_Descriptor;
1109 Path_Name : Path_Name_Type;
1112 Prj.Env.Create_Temp_File
1113 (Shared => Project_Tree.Shared,
1115 Path_Name => Path_Name,
1116 File_Use => "configuration file");
1118 if Path_FD /= Invalid_FD then
1120 Temp_Dir : constant String :=
1121 Containing_Directory
1122 (Get_Name_String (Path_Name));
1124 GNAT.OS_Lib.Close (Path_FD);
1126 new String'(Temp_Dir
&
1127 Directory_Separator
&
1129 Delete_File
(Get_Name_String
(Path_Name
));
1133 -- We'll have an error message later on
1135 Args
(3) := new String'(Obj_Dir & Auto_Cgpr);
1140 Args (3) := Conf_File_Name;
1145 if Selected_Target /= null and then
1146 Selected_Target.all /= ""
1150 new String'("--target=" & Selected_Target
.all);
1153 elsif Normalized_Hostname
/= "" then
1154 if At_Least_One_Compiler_Command
then
1155 Args
(4) := new String'("--target=all");
1157 Args (4) := new String'("--target=" & Normalized_Hostname
);
1163 if not Verbose_Mode
then
1164 Arg_Last
:= Arg_Last
+ 1;
1165 Args
(Arg_Last
) := new String'("-q");
1168 if Verbose_Mode then
1169 Write_Str (Gprconfig_Name);
1171 for J in 1 .. Arg_Last loop
1173 Write_Str (Args (J).all);
1176 for J in Config_Switches'Range loop
1178 Write_Str (Config_Switches (J).all);
1181 for J in Db_Switches'Range loop
1183 Write_Str (Db_Switches (J).all);
1188 elsif not Quiet_Output then
1190 -- Display no message if we are creating auto.cgpr, unless in
1193 if Config_File_Name'Length > 0 or else Verbose_Mode then
1194 Write_Str ("creating ");
1195 Write_Str (Simple_Name (Args (3).all));
1200 Spawn (Gprconfig_Path.all, Args (1 .. Arg_Last) &
1201 Config_Switches.all & Db_Switches.all,
1204 Free (Config_Switches);
1206 Config_File_Path := Locate_Config_File (Args (3).all);
1208 if Config_File_Path = null then
1209 Raise_Invalid_Config
1210 ("could not create " & Args (3).all);
1213 for F in Args'Range loop
1219 ---------------------
1220 -- Get_Db_Switches --
1221 ---------------------
1223 function Get_Db_Switches return Argument_List_Access is
1224 Result : Argument_List_Access;
1228 (2 * Db_Switch_Args.Last) + Boolean'Pos (not Load_Standard_Base);
1229 Result := new Argument_List (1 .. Nmb_Arg);
1231 if Nmb_Arg /= 0 then
1232 for J in 1 .. Db_Switch_Args.Last loop
1233 Result (2 * J - 1) :=
1234 new String'("--db");
1236 new String'(Get_Name_String (Db_Switch_Args.Table (J)));
1239 if not Load_Standard_Base then
1240 Result (Result'Last) := new String'("--db-");
1245 end Get_Db_Switches
;
1247 -------------------------
1248 -- Get_Config_Switches --
1249 -------------------------
1251 function Get_Config_Switches
return Argument_List_Access
is
1253 package Language_Htable
is new GNAT
.HTable
.Simple_HTable
1254 (Header_Num
=> Prj
.Header_Num
,
1256 No_Element
=> No_Name
,
1260 -- Hash table to keep the languages used in the project tree
1262 IDE
: constant Package_Id
:=
1263 Value_Of
(Name_Ide
, Project
.Decl
.Packages
, Shared
);
1265 procedure Add_Config_Switches_For_Project
1266 (Project
: Project_Id
;
1267 Tree
: Project_Tree_Ref
;
1268 With_State
: in out Integer);
1269 -- Add all --config switches for this project. This is also called
1270 -- for aggregate projects.
1272 -------------------------------------
1273 -- Add_Config_Switches_For_Project --
1274 -------------------------------------
1276 procedure Add_Config_Switches_For_Project
1277 (Project
: Project_Id
;
1278 Tree
: Project_Tree_Ref
;
1279 With_State
: in out Integer)
1281 pragma Unreferenced
(With_State
);
1283 Shared
: constant Shared_Project_Tree_Data_Access
:= Tree
.Shared
;
1285 Variable
: Variable_Value
;
1286 Check_Default
: Boolean;
1288 List
: String_List_Id
;
1289 Elem
: String_Element
;
1292 if Might_Have_Sources
(Project
) then
1294 Value_Of
(Name_Languages
, Project
.Decl
.Attributes
, Shared
);
1296 if Variable
= Nil_Variable_Value
or else Variable
.Default
then
1298 -- Languages is not declared. If it is not an extending
1299 -- project, or if it extends a project with no Languages,
1300 -- check for Default_Language.
1302 Check_Default
:= Project
.Extends
= No_Project
;
1304 if not Check_Default
then
1308 Project
.Extends
.Decl
.Attributes
,
1311 Variable
/= Nil_Variable_Value
1312 and then Variable
.Values
= Nil_String
;
1315 if Check_Default
then
1318 (Name_Default_Language
,
1319 Project
.Decl
.Attributes
,
1322 if Variable
/= Nil_Variable_Value
1323 and then not Variable
.Default
1325 Get_Name_String
(Variable
.Value
);
1326 To_Lower
(Name_Buffer
(1 .. Name_Len
));
1328 Language_Htable
.Set
(Lang
, Lang
);
1330 -- If no default language is declared, default to Ada
1333 Language_Htable
.Set
(Name_Ada
, Name_Ada
);
1337 elsif Variable
.Values
/= Nil_String
then
1339 -- Attribute Languages is declared with a non empty list:
1340 -- put all the languages in Language_HTable.
1342 List
:= Variable
.Values
;
1343 while List
/= Nil_String
loop
1344 Elem
:= Shared
.String_Elements
.Table
(List
);
1346 Get_Name_String
(Elem
.Value
);
1347 To_Lower
(Name_Buffer
(1 .. Name_Len
));
1349 Language_Htable
.Set
(Lang
, Lang
);
1355 end Add_Config_Switches_For_Project
;
1357 procedure For_Every_Imported_Project
is new For_Every_Project_Imported
1358 (State
=> Integer, Action
=> Add_Config_Switches_For_Project
);
1359 -- Document this procedure ???
1365 Result
: Argument_List_Access
;
1366 Variable
: Variable_Value
;
1367 Dummy
: Integer := 0;
1369 -- Start of processing for Get_Config_Switches
1372 For_Every_Imported_Project
1374 Tree
=> Project_Tree
,
1375 With_State
=> Dummy
,
1376 Include_Aggregated
=> True);
1378 Name
:= Language_Htable
.Get_First
;
1380 while Name
/= No_Name
loop
1382 Name
:= Language_Htable
.Get_Next
;
1385 Result
:= new String_List
(1 .. Count
);
1388 Name
:= Language_Htable
.Get_First
;
1389 while Name
/= No_Name
loop
1391 -- Check if IDE'Compiler_Command is declared for the language.
1392 -- If it is, use its value to invoke gprconfig.
1397 Attribute_Or_Array_Name
=> Name_Compiler_Command
,
1400 Force_Lower_Case_Index
=> True);
1403 Config_Command
: constant String :=
1404 "--config=" & Get_Name_String
(Name
);
1406 Runtime_Name
: constant String := Runtime_Name_For
(Name
);
1409 -- In CodePeer mode, we do not take into account any compiler
1410 -- command from the package IDE.
1413 or else Variable
= Nil_Variable_Value
1414 or else Length_Of_Name
(Variable
.Value
) = 0
1417 new String'(Config_Command & ",," & Runtime_Name);
1420 At_Least_One_Compiler_Command := True;
1423 Compiler_Command : constant String :=
1424 Get_Name_String (Variable.Value);
1427 if Is_Absolute_Path (Compiler_Command) then
1430 (Config_Command
& ",," & Runtime_Name
& ","
1431 & Containing_Directory
(Compiler_Command
) & ","
1432 & Simple_Name
(Compiler_Command
));
1436 (Config_Command & ",," & Runtime_Name & ",,"
1437 & Compiler_Command);
1444 Name := Language_Htable.Get_Next;
1448 end Get_Config_Switches;
1450 ------------------------
1451 -- Might_Have_Sources --
1452 ------------------------
1454 function Might_Have_Sources (Project : Project_Id) return Boolean is
1455 Variable : Variable_Value;
1459 Value_Of (Name_Source_Dirs, Project.Decl.Attributes, Shared);
1461 if Variable = Nil_Variable_Value
1462 or else Variable.Default
1463 or else Variable.Values /= Nil_String
1466 Value_Of (Name_Source_Files, Project.Decl.Attributes, Shared);
1467 return Variable = Nil_Variable_Value
1468 or else Variable.Default
1469 or else Variable.Values /= Nil_String;
1474 end Might_Have_Sources;
1479 Config_Project_Node : Project_Node_Id := Empty_Node;
1481 -- Start of processing for Get_Or_Create_Configuration_File
1484 pragma Assert (Prj.Env.Is_Initialized (Env.Project_Path));
1486 Free (Config_File_Path);
1487 Config := No_Project;
1490 Get_Project_Runtimes;
1491 Check_Builder_Switches;
1493 -- Do not attempt to find a configuration project file when
1494 -- Config_File_Name is No_Configuration_File.
1496 if Config_File_Name = No_Configuration_File then
1497 Config_File_Path := null;
1500 if Conf_File_Name'Length > 0 then
1501 Config_File_Path := Locate_Config_File (Conf_File_Name.all);
1503 Config_File_Path := Locate_Config_File (Default_File_Name);
1506 if Config_File_Path = null then
1507 if not Allow_Automatic_Generation
1508 and then Conf_File_Name'Length > 0
1510 Raise_Invalid_Config
1511 ("could not locate main configuration project "
1512 & Conf_File_Name.all);
1517 Automatically_Generated :=
1518 Allow_Automatic_Generation and then Config_File_Path = null;
1520 <<Process_Config_File>>
1522 if Automatically_Generated then
1524 -- This might raise an Invalid_Config exception
1528 -- If the config file is not auto-generated, warn if there is any --RTS
1529 -- switch, but not when the config file is generated in memory.
1532 and then RTS_Languages.Get_First /= No_Name
1533 and then Opt.Warning_Mode /= Opt.Suppress
1534 and then On_Load_Config = null
1538 "runtimes are taken into account only in auto-configuration");
1541 -- Parse the configuration file
1543 if Verbose_Mode and then Config_File_Path /= null then
1544 Write_Str ("Checking configuration ");
1545 Write_Line (Config_File_Path.all);
1548 if Config_File_Path /= null then
1550 (In_Tree => Project_Node_Tree,
1551 Project => Config_Project_Node,
1552 Project_File_Name => Config_File_Path.all,
1553 Errout_Handling => Prj.Part.Finalize_If_Error,
1554 Packages_To_Check => Packages_To_Check,
1555 Current_Directory => Current_Directory,
1556 Is_Config_File => True,
1559 Config_Project_Node := Empty_Node;
1562 if On_Load_Config /= null then
1564 (Config_File => Config_Project_Node,
1565 Project_Node_Tree => Project_Node_Tree);
1568 if Config_Project_Node /= Empty_Node then
1569 Prj.Proc.Process_Project_Tree_Phase_1
1570 (In_Tree => Project_Tree,
1572 Packages_To_Check => Packages_To_Check,
1574 From_Project_Node => Config_Project_Node,
1575 From_Project_Node_Tree => Project_Node_Tree,
1577 Reset_Tree => False,
1578 On_New_Tree_Loaded => null);
1581 if Config_Project_Node = Empty_Node or else Config = No_Project then
1582 Raise_Invalid_Config
1583 ("processing of configuration project """
1584 & Config_File_Path.all & """ failed");
1587 -- Check that the target of the configuration file is the one the user
1588 -- specified on the command line. We do not need to check that when in
1589 -- auto-conf mode, since the appropriate target was passed to gprconfig.
1591 if not Automatically_Generated
1594 (Config, Autoconf_Specified, Project_Tree, Selected_Target.all)
1596 Automatically_Generated := True;
1597 goto Process_Config_File;
1599 end Get_Or_Create_Configuration_File;
1601 ------------------------
1602 -- Locate_Config_File --
1603 ------------------------
1605 function Locate_Config_File (Name : String) return String_Access is
1606 Prefix_Path : constant String := Executable_Prefix_Path;
1608 if Prefix_Path'Length /= 0 then
1609 return Locate_Regular_File
1611 "." & Path_Separator &
1612 Prefix_Path & "share" & Directory_Separator & "gpr");
1614 return Locate_Regular_File (Name, ".");
1616 end Locate_Config_File;
1618 ------------------------------------
1619 -- Parse_Project_And_Apply_Config --
1620 ------------------------------------
1622 procedure Parse_Project_And_Apply_Config
1623 (Main_Project : out Prj.Project_Id;
1624 User_Project_Node : out Prj.Tree.Project_Node_Id;
1625 Config_File_Name : String := "";
1626 Autoconf_Specified : Boolean;
1627 Project_File_Name : String;
1628 Project_Tree : Prj.Project_Tree_Ref;
1629 Project_Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
1630 Env : in out Prj.Tree.Environment;
1631 Packages_To_Check : String_List_Access;
1632 Allow_Automatic_Generation : Boolean := True;
1633 Automatically_Generated : out Boolean;
1634 Config_File_Path : out String_Access;
1635 Target_Name : String := "";
1636 Normalized_Hostname : String;
1637 On_Load_Config : Config_File_Hook := null;
1638 Implicit_Project : Boolean := False;
1639 On_New_Tree_Loaded : Prj.Proc.Tree_Loaded_Callback := null)
1641 Success : Boolean := False;
1642 Target_Try_Again : Boolean := True;
1643 Config_Try_Again : Boolean;
1645 Finalization : Prj.Part.Errout_Mode := Prj.Part.Always_Finalize;
1647 S : State := No_State;
1649 Conf_File_Name : String_Access := new String'(Config_File_Name
);
1651 procedure Add_Directory
(Dir
: String);
1652 -- Add a directory at the end of the Project Path
1654 Auto_Generated
: Boolean;
1660 procedure Add_Directory
(Dir
: String) is
1662 if Opt
.Verbose_Mode
then
1663 Write_Line
(" Adding directory """ & Dir
& """");
1666 Prj
.Env
.Add_Directories
(Env
.Project_Path
, Dir
);
1670 pragma Assert
(Prj
.Env
.Is_Initialized
(Env
.Project_Path
));
1672 -- Start with ignoring missing withed projects
1674 Set_Ignore_Missing_With
(Env
.Flags
, True);
1676 -- Note: If in fact the config file is automatically generated, then
1677 -- Automatically_Generated will be set to True after invocation of
1678 -- Process_Project_And_Apply_Config.
1680 Automatically_Generated
:= False;
1682 -- Record Target_Value and Target_Origin
1684 if Target_Name
= "" then
1685 Opt
.Target_Value
:= new String'(Normalized_Hostname);
1686 Opt.Target_Origin := Default;
1688 Opt.Target_Value := new String'(Target_Name
);
1689 Opt
.Target_Origin
:= Specified
;
1694 -- Parse the user project tree
1696 Project_Node_Tree
.Incomplete_With
:= False;
1697 Env
.Flags
.Incomplete_Withs
:= False;
1698 Prj
.Initialize
(Project_Tree
);
1700 Main_Project
:= No_Project
;
1703 (In_Tree
=> Project_Node_Tree
,
1704 Project
=> User_Project_Node
,
1705 Project_File_Name
=> Project_File_Name
,
1706 Errout_Handling
=> Finalization
,
1707 Packages_To_Check
=> Packages_To_Check
,
1708 Current_Directory
=> Current_Directory
,
1709 Is_Config_File
=> False,
1711 Implicit_Project
=> Implicit_Project
);
1713 Finalization
:= Prj
.Part
.Finalize_If_Error
;
1715 if User_Project_Node
= Empty_Node
then
1719 -- If --target was not specified on the command line, then do Phase 1 to
1720 -- check if attribute Target is declared in the main project.
1722 if Opt
.Target_Origin
/= Specified
then
1723 Main_Project
:= No_Project
;
1724 Process_Project_Tree_Phase_1
1725 (In_Tree
=> Project_Tree
,
1726 Project
=> Main_Project
,
1727 Packages_To_Check
=> Packages_To_Check
,
1729 From_Project_Node
=> User_Project_Node
,
1730 From_Project_Node_Tree
=> Project_Node_Tree
,
1733 On_New_Tree_Loaded
=> On_New_Tree_Loaded
);
1736 Main_Project
:= No_Project
;
1741 Variable
: constant Variable_Value
:=
1744 Main_Project
.Decl
.Attributes
,
1745 Project_Tree
.Shared
);
1747 if Variable
/= Nil_Variable_Value
1748 and then not Variable
.Default
1750 Get_Name_String
(Variable
.Value
) /= Opt
.Target_Value
.all
1752 if Target_Try_Again
then
1754 new String'(Get_Name_String (Variable.Value));
1755 Target_Try_Again := False;
1761 "inconsistent value of attribute Target");
1767 -- If there are missing withed projects, the projects will be parsed
1768 -- again after the project path is extended with directories rooted
1769 -- at the compiler roots.
1771 Config_Try_Again := Project_Node_Tree.Incomplete_With;
1773 Process_Project_And_Apply_Config
1774 (Main_Project => Main_Project,
1775 User_Project_Node => User_Project_Node,
1776 Config_File_Name => Conf_File_Name.all,
1777 Autoconf_Specified => Autoconf_Specified,
1778 Project_Tree => Project_Tree,
1779 Project_Node_Tree => Project_Node_Tree,
1781 Packages_To_Check => Packages_To_Check,
1782 Allow_Automatic_Generation => Allow_Automatic_Generation,
1783 Automatically_Generated => Auto_Generated,
1784 Config_File_Path => Config_File_Path,
1785 Target_Name => Target_Name,
1786 Normalized_Hostname => Normalized_Hostname,
1787 On_Load_Config => On_Load_Config,
1788 On_New_Tree_Loaded => On_New_Tree_Loaded,
1789 Do_Phase_1 => Opt.Target_Origin = Specified);
1791 if Auto_Generated then
1792 Automatically_Generated := True;
1795 -- Exit if there was an error. Otherwise, if Config_Try_Again is True,
1796 -- update the project path and try again.
1798 if Main_Project /= No_Project and then Config_Try_Again then
1799 Set_Ignore_Missing_With (Env.Flags, False);
1801 if Config_File_Path /= null then
1802 Conf_File_Name := new String'(Config_File_Path
.all);
1805 -- For the second time the project files are parsed, the warning for
1806 -- --RTS= being only taken into account in auto-configuration are
1807 -- suppressed, as we are no longer in auto-configuration.
1809 Warn_For_RTS
:= False;
1811 -- Add the default directories corresponding to the compilers
1814 (By
=> Main_Project
,
1815 Tree
=> Project_Tree
,
1817 Include_Aggregated
=> True,
1818 Imported_First
=> False);
1821 Compiler_Root
: Compiler_Root_Ptr
;
1822 Prefix
: String_Access
;
1823 Runtime_Root
: Runtime_Root_Ptr
;
1824 Path_Value
: constant String_Access
:= Getenv
("PATH");
1827 if Opt
.Verbose_Mode
then
1828 Write_Line
("Setting the default project search directories");
1830 if Prj
.Current_Verbosity
= High
then
1831 if Path_Value
= null or else Path_Value
'Length = 0 then
1832 Write_Line
("No environment variable PATH");
1835 Write_Line
("PATH =");
1836 Write_Line
(" " & Path_Value
.all);
1841 -- Reorder the compiler roots in the PATH order
1843 if First_Compiler_Root
/= null
1844 and then First_Compiler_Root
.Next
/= null
1847 Pred
: Compiler_Root_Ptr
;
1848 First_New_Comp
: Compiler_Root_Ptr
:= null;
1849 New_Comp
: Compiler_Root_Ptr
:= null;
1850 First
: Positive := Path_Value
'First;
1852 Path_Last
: Positive;
1854 while First
<= Path_Value
'Last loop
1857 if Path_Value
(First
) /= Path_Separator
then
1858 while Last
< Path_Value
'Last
1859 and then Path_Value
(Last
+ 1) /= Path_Separator
1865 while Path_Last
> First
1867 Path_Value
(Path_Last
) = Directory_Separator
1869 Path_Last
:= Path_Last
- 1;
1872 if Path_Last
> First
+ 4
1874 Path_Value
(Path_Last
- 2 .. Path_Last
) = "bin"
1876 Path_Value
(Path_Last
- 3) = Directory_Separator
1878 Path_Last
:= Path_Last
- 4;
1880 Compiler_Root
:= First_Compiler_Root
;
1881 while Compiler_Root
/= null
1882 and then Compiler_Root
.Root
.all /=
1883 Path_Value
(First
.. Path_Last
)
1885 Pred
:= Compiler_Root
;
1886 Compiler_Root
:= Compiler_Root
.Next
;
1889 if Compiler_Root
/= null then
1891 First_Compiler_Root
:=
1892 First_Compiler_Root
.Next
;
1894 Pred
.Next
:= Compiler_Root
.Next
;
1897 if First_New_Comp
= null then
1898 First_New_Comp
:= Compiler_Root
;
1900 New_Comp
.Next
:= Compiler_Root
;
1903 New_Comp
:= Compiler_Root
;
1904 New_Comp
.Next
:= null;
1912 if First_New_Comp
/= null then
1913 New_Comp
.Next
:= First_Compiler_Root
;
1914 First_Compiler_Root
:= First_New_Comp
;
1919 -- Now that the compiler roots are in a correct order, add the
1920 -- directories corresponding to these compiler roots in the
1923 Compiler_Root
:= First_Compiler_Root
;
1924 while Compiler_Root
/= null loop
1925 Prefix
:= Compiler_Root
.Root
;
1927 Runtime_Root
:= Compiler_Root
.Runtimes
;
1928 while Runtime_Root
/= null loop
1930 (Runtime_Root
.Root
.all &
1931 Directory_Separator
&
1933 Directory_Separator
&
1936 (Runtime_Root
.Root
.all &
1937 Directory_Separator
&
1939 Directory_Separator
&
1941 Runtime_Root
:= Runtime_Root
.Next
;
1946 Directory_Separator
&
1947 Opt
.Target_Value
.all &
1948 Directory_Separator
&
1950 Directory_Separator
&
1954 Directory_Separator
&
1955 Opt
.Target_Value
.all &
1956 Directory_Separator
&
1958 Directory_Separator
&
1962 Directory_Separator
&
1964 Directory_Separator
&
1968 Directory_Separator
&
1970 Directory_Separator
&
1972 Compiler_Root
:= Compiler_Root
.Next
;
1976 -- And parse again the project files. There will be no missing
1977 -- withed projects, as Ignore_Missing_With is set to False in
1978 -- the environment flags, so there is no risk of endless loop here.
1982 end Parse_Project_And_Apply_Config
;
1984 --------------------------------------
1985 -- Process_Project_And_Apply_Config --
1986 --------------------------------------
1988 procedure Process_Project_And_Apply_Config
1989 (Main_Project
: out Prj
.Project_Id
;
1990 User_Project_Node
: Prj
.Tree
.Project_Node_Id
;
1991 Config_File_Name
: String := "";
1992 Autoconf_Specified
: Boolean;
1993 Project_Tree
: Prj
.Project_Tree_Ref
;
1994 Project_Node_Tree
: Prj
.Tree
.Project_Node_Tree_Ref
;
1995 Env
: in out Prj
.Tree
.Environment
;
1996 Packages_To_Check
: String_List_Access
;
1997 Allow_Automatic_Generation
: Boolean := True;
1998 Automatically_Generated
: out Boolean;
1999 Config_File_Path
: out String_Access
;
2000 Target_Name
: String := "";
2001 Normalized_Hostname
: String;
2002 On_Load_Config
: Config_File_Hook
:= null;
2003 Reset_Tree
: Boolean := True;
2004 On_New_Tree_Loaded
: Prj
.Proc
.Tree_Loaded_Callback
:= null;
2005 Do_Phase_1
: Boolean := True)
2007 Shared
: constant Shared_Project_Tree_Data_Access
:=
2008 Project_Tree
.Shared
;
2009 Main_Config_Project
: Project_Id
;
2012 Conf_Project
: Project_Id
:= No_Project
;
2013 -- The object directory of this project is used to store the config
2014 -- project file in auto-configuration. Set by Check_Project below.
2016 procedure Check_Project
(Project
: Project_Id
);
2017 -- Look for a non aggregate project. If one is found, put its project Id
2024 procedure Check_Project
(Project
: Project_Id
) is
2026 if Project
.Qualifier
= Aggregate
2028 Project
.Qualifier
= Aggregate_Library
2031 List
: Aggregated_Project_List
:= Project
.Aggregated_Projects
;
2034 -- Look for a non aggregate project until one is found
2036 while Conf_Project
= No_Project
and then List
/= null loop
2037 Check_Project
(List
.Project
);
2043 Conf_Project
:= Project
;
2047 -- Start of processing for Process_Project_And_Apply_Config
2050 Automatically_Generated
:= False;
2053 Main_Project
:= No_Project
;
2054 Process_Project_Tree_Phase_1
2055 (In_Tree
=> Project_Tree
,
2056 Project
=> Main_Project
,
2057 Packages_To_Check
=> Packages_To_Check
,
2059 From_Project_Node
=> User_Project_Node
,
2060 From_Project_Node_Tree
=> Project_Node_Tree
,
2062 Reset_Tree
=> Reset_Tree
,
2063 On_New_Tree_Loaded
=> On_New_Tree_Loaded
);
2066 Main_Project
:= No_Project
;
2071 if Project_Tree
.Source_Info_File_Name
/= null then
2072 if not Is_Absolute_Path
(Project_Tree
.Source_Info_File_Name
.all) then
2074 Obj_Dir
: constant Variable_Value
:=
2077 Main_Project
.Decl
.Attributes
,
2081 if Obj_Dir
= Nil_Variable_Value
or else Obj_Dir
.Default
then
2082 Get_Name_String
(Main_Project
.Directory
.Display_Name
);
2085 if Is_Absolute_Path
(Get_Name_String
(Obj_Dir
.Value
)) then
2086 Get_Name_String
(Obj_Dir
.Value
);
2090 Add_Str_To_Name_Buffer
2091 (Get_Name_String
(Main_Project
.Directory
.Display_Name
));
2092 Add_Str_To_Name_Buffer
(Get_Name_String
(Obj_Dir
.Value
));
2096 Add_Char_To_Name_Buffer
(Directory_Separator
);
2097 Add_Str_To_Name_Buffer
(Project_Tree
.Source_Info_File_Name
.all);
2098 Free
(Project_Tree
.Source_Info_File_Name
);
2099 Project_Tree
.Source_Info_File_Name
:=
2100 new String'(Name_Buffer (1 .. Name_Len));
2104 Read_Source_Info_File (Project_Tree);
2107 -- Get the first project that is not an aggregate project or an
2108 -- aggregate library project. The object directory of this project will
2109 -- be used to store the config project file in auto-configuration.
2111 Check_Project (Main_Project);
2113 -- Fail if there is only aggregate projects and aggregate library
2114 -- projects in the project tree.
2116 if Conf_Project = No_Project then
2117 Raise_Invalid_Config ("there are no non-aggregate projects");
2120 -- Find configuration file
2122 Get_Or_Create_Configuration_File
2123 (Config => Main_Config_Project,
2124 Project => Main_Project,
2125 Conf_Project => Conf_Project,
2126 Project_Tree => Project_Tree,
2127 Project_Node_Tree => Project_Node_Tree,
2129 Allow_Automatic_Generation => Allow_Automatic_Generation,
2130 Config_File_Name => Config_File_Name,
2131 Autoconf_Specified => Autoconf_Specified,
2132 Target_Name => Target_Name,
2133 Normalized_Hostname => Normalized_Hostname,
2134 Packages_To_Check => Packages_To_Check,
2135 Config_File_Path => Config_File_Path,
2136 Automatically_Generated => Automatically_Generated,
2137 On_Load_Config => On_Load_Config);
2139 Apply_Config_File (Main_Config_Project, Project_Tree);
2141 -- Finish processing the user's project
2143 Prj.Proc.Process_Project_Tree_Phase_2
2144 (In_Tree => Project_Tree,
2145 Project => Main_Project,
2147 From_Project_Node => User_Project_Node,
2148 From_Project_Node_Tree => Project_Node_Tree,
2152 if Project_Tree.Source_Info_File_Name /= null
2153 and then not Project_Tree.Source_Info_File_Exists
2155 Write_Source_Info_File (Project_Tree);
2159 Main_Project := No_Project;
2161 end Process_Project_And_Apply_Config;
2163 --------------------------
2164 -- Raise_Invalid_Config --
2165 --------------------------
2167 procedure Raise_Invalid_Config (Msg : String) is
2169 Raise_Exception (Invalid_Config'Identity, Msg);
2170 end Raise_Invalid_Config;
2172 ----------------------
2173 -- Runtime_Name_For --
2174 ----------------------
2176 function Runtime_Name_For (Language : Name_Id) return String is
2178 if RTS_Languages.Get (Language) /= No_Name then
2179 return Get_Name_String (RTS_Languages.Get (Language));
2183 end Runtime_Name_For;
2185 --------------------------
2186 -- Runtime_Name_Set_For --
2187 --------------------------
2189 function Runtime_Name_Set_For (Language : Name_Id) return Boolean is
2191 return RTS_Languages.Get (Language) /= No_Name;
2192 end Runtime_Name_Set_For;
2194 ---------------------
2195 -- Set_Runtime_For --
2196 ---------------------
2198 procedure Set_Runtime_For (Language : Name_Id; RTS_Name : String) is
2200 Name_Len := RTS_Name'Length;
2201 Name_Buffer (1 .. Name_Len) := RTS_Name;
2202 RTS_Languages.Set (Language, Name_Find);
2203 end Set_Runtime_For;
2205 ----------------------------
2206 -- Look_For_Project_Paths --
2207 ----------------------------
2209 procedure Look_For_Project_Paths
2210 (Project : Project_Id;
2211 Tree : Project_Tree_Ref;
2212 With_State : in out State)
2214 Lang_Id : Language_Ptr;
2215 Compiler_Root : Compiler_Root_Ptr;
2216 Runtime_Root : Runtime_Root_Ptr;
2217 Comp_Driver : String_Access;
2218 Comp_Dir : String_Access;
2219 Prefix : String_Access;
2221 pragma Unreferenced (Tree);
2224 With_State := No_State;
2226 Lang_Id := Project.Languages;
2227 while Lang_Id /= No_Language_Index loop
2228 if Lang_Id.Config.Compiler_Driver /= No_File then
2231 (Get_Name_String
(Lang_Id
.Config
.Compiler_Driver
));
2233 -- Get the absolute path of the compiler driver
2235 if not Is_Absolute_Path
(Comp_Driver
.all) then
2236 Comp_Driver
:= Locate_Exec_On_Path
(Comp_Driver
.all);
2239 if Comp_Driver
/= null and then Comp_Driver
'Length > 0 then
2242 (Containing_Directory (Comp_Driver.all));
2244 -- Consider only the compiler drivers that are in "bin"
2247 if Simple_Name (Comp_Dir.all) = "bin" then
2249 new String'(Containing_Directory
(Comp_Dir
.all));
2251 -- Check if the compiler root is already in the list. If it
2252 -- is not, add it to the list.
2254 Compiler_Root
:= First_Compiler_Root
;
2255 while Compiler_Root
/= null loop
2256 exit when Prefix
.all = Compiler_Root
.Root
.all;
2257 Compiler_Root
:= Compiler_Root
.Next
;
2260 if Compiler_Root
= null then
2261 First_Compiler_Root
:=
2262 new Compiler_Root_Data
'
2265 Next => First_Compiler_Root);
2266 Compiler_Root := First_Compiler_Root;
2269 -- If there is a runtime for this compiler, check if it is
2270 -- recorded with the compiler root. If it is not, record
2274 Runtime : constant String :=
2275 Runtime_Name_For (Lang_Id.Name);
2276 Root : String_Access;
2279 if Runtime'Length > 0 then
2280 if Is_Absolute_Path (Runtime) then
2281 Root := new String'(Runtime
);
2287 Directory_Separator &
2288 Opt.Target_Value.all &
2289 Directory_Separator &
2293 Runtime_Root := Compiler_Root.Runtimes;
2294 while Runtime_Root /= null loop
2295 exit when Root.all = Runtime_Root.Root.all;
2296 Runtime_Root := Runtime_Root.Next;
2299 if Runtime_Root = null then
2300 Compiler_Root.Runtimes :=
2301 new Runtime_Root_Data'
2303 Next
=> Compiler_Root
.Runtimes
);
2311 Lang_Id
:= Lang_Id
.Next
;
2313 end Look_For_Project_Paths
;