1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2006-2014, 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 Obj_Dir
= Nil_Variable_Value
or else Obj_Dir
.Default
then
966 Get_Name_String
(Conf_Project
.Directory
.Display_Name
);
969 if Is_Absolute_Path
(Get_Name_String
(Obj_Dir
.Value
)) then
970 Get_Name_String
(Obj_Dir
.Value
);
974 Add_Str_To_Name_Buffer
975 (Get_Name_String
(Conf_Project
.Directory
.Display_Name
));
976 Add_Str_To_Name_Buffer
(Get_Name_String
(Obj_Dir
.Value
));
980 if Subdirs
/= null then
981 Add_Char_To_Name_Buffer
(Directory_Separator
);
982 Add_Str_To_Name_Buffer
(Subdirs
.all);
985 for J
in 1 .. Name_Len
loop
986 if Name_Buffer
(J
) = '/' then
987 Name_Buffer
(J
) := Directory_Separator
;
991 -- Make sure that Obj_Dir ends with a directory separator
993 if Name_Buffer
(Name_Len
) /= Directory_Separator
then
994 Name_Len
:= Name_Len
+ 1;
995 Name_Buffer
(Name_Len
) := Directory_Separator
;
999 Obj_Dir
: constant String := Name_Buffer
(1 .. Name_Len
);
1000 Config_Switches
: Argument_List_Access
;
1001 Db_Switches
: Argument_List_Access
;
1002 Args
: Argument_List
(1 .. 5);
1003 Arg_Last
: Positive;
1004 Obj_Dir_Exists
: Boolean := True;
1007 -- Check if the object directory exists. If Setup_Projects is True
1008 -- (-p) and directory does not exist, attempt to create it.
1009 -- Otherwise, if directory does not exist, fail without calling
1012 if not Is_Directory
(Obj_Dir
)
1013 and then (Setup_Projects
or else Subdirs
/= null)
1016 Create_Path
(Obj_Dir
);
1018 if not Quiet_Output
then
1019 Write_Str
("object directory """);
1020 Write_Str
(Obj_Dir
);
1021 Write_Line
(""" created");
1026 Raise_Invalid_Config
1027 ("could not create object directory " & Obj_Dir
);
1031 if not Is_Directory
(Obj_Dir
) then
1032 case Env
.Flags
.Require_Obj_Dirs
is
1034 Raise_Invalid_Config
1035 ("object directory " & Obj_Dir
& " does not exist");
1040 "?object directory " & Obj_Dir
& " does not exist");
1041 Obj_Dir_Exists
:= False;
1048 -- Get the config switches. This should be done only now, as some
1049 -- runtimes may have been found in the Builder switches.
1051 Config_Switches
:= Get_Config_Switches
;
1053 -- Get eventual --db switches
1055 Db_Switches
:= Get_Db_Switches
;
1059 Args
(1) := new String'("--batch");
1060 Args (2) := new String'("-o");
1062 -- If no config file was specified, set the auto.cgpr one
1064 if Conf_File_Name
'Length = 0 then
1065 if Obj_Dir_Exists
then
1066 Args
(3) := new String'(Obj_Dir & Auto_Cgpr);
1070 Path_FD : File_Descriptor;
1071 Path_Name : Path_Name_Type;
1074 Prj.Env.Create_Temp_File
1075 (Shared => Project_Tree.Shared,
1077 Path_Name => Path_Name,
1078 File_Use => "configuration file");
1080 if Path_FD /= Invalid_FD then
1082 Temp_Dir : constant String :=
1083 Containing_Directory
1084 (Get_Name_String (Path_Name));
1086 GNAT.OS_Lib.Close (Path_FD);
1088 new String'(Temp_Dir
&
1089 Directory_Separator
&
1091 Delete_File
(Get_Name_String
(Path_Name
));
1095 -- We'll have an error message later on
1097 Args
(3) := new String'(Obj_Dir & Auto_Cgpr);
1102 Args (3) := Conf_File_Name;
1107 if Selected_Target /= null and then
1108 Selected_Target.all /= ""
1112 new String'("--target=" & Selected_Target
.all);
1115 elsif Normalized_Hostname
/= "" then
1116 if At_Least_One_Compiler_Command
then
1117 Args
(4) := new String'("--target=all");
1119 Args (4) := new String'("--target=" & Normalized_Hostname
);
1125 if not Verbose_Mode
then
1126 Arg_Last
:= Arg_Last
+ 1;
1127 Args
(Arg_Last
) := new String'("-q");
1130 if Verbose_Mode then
1131 Write_Str (Gprconfig_Name);
1133 for J in 1 .. Arg_Last loop
1135 Write_Str (Args (J).all);
1138 for J in Config_Switches'Range loop
1140 Write_Str (Config_Switches (J).all);
1143 for J in Db_Switches'Range loop
1145 Write_Str (Db_Switches (J).all);
1150 elsif not Quiet_Output then
1152 -- Display no message if we are creating auto.cgpr, unless in
1155 if Config_File_Name'Length > 0 or else Verbose_Mode then
1156 Write_Str ("creating ");
1157 Write_Str (Simple_Name (Args (3).all));
1162 Spawn (Gprconfig_Path.all, Args (1 .. Arg_Last) &
1163 Config_Switches.all & Db_Switches.all,
1166 Free (Config_Switches);
1168 Config_File_Path := Locate_Config_File (Args (3).all);
1170 if Config_File_Path = null then
1171 Raise_Invalid_Config
1172 ("could not create " & Args (3).all);
1175 for F in Args'Range loop
1181 ---------------------
1182 -- Get_Db_Switches --
1183 ---------------------
1185 function Get_Db_Switches return Argument_List_Access is
1186 Result : Argument_List_Access;
1190 (2 * Db_Switch_Args.Last) + Boolean'Pos (not Load_Standard_Base);
1191 Result := new Argument_List (1 .. Nmb_Arg);
1193 if Nmb_Arg /= 0 then
1194 for J in 1 .. Db_Switch_Args.Last loop
1195 Result (2 * J - 1) :=
1196 new String'("--db");
1198 new String'(Get_Name_String (Db_Switch_Args.Table (J)));
1201 if not Load_Standard_Base then
1202 Result (Result'Last) := new String'("--db-");
1207 end Get_Db_Switches
;
1209 -------------------------
1210 -- Get_Config_Switches --
1211 -------------------------
1213 function Get_Config_Switches
return Argument_List_Access
is
1215 package Language_Htable
is new GNAT
.HTable
.Simple_HTable
1216 (Header_Num
=> Prj
.Header_Num
,
1218 No_Element
=> No_Name
,
1222 -- Hash table to keep the languages used in the project tree
1224 IDE
: constant Package_Id
:=
1225 Value_Of
(Name_Ide
, Project
.Decl
.Packages
, Shared
);
1227 procedure Add_Config_Switches_For_Project
1228 (Project
: Project_Id
;
1229 Tree
: Project_Tree_Ref
;
1230 With_State
: in out Integer);
1231 -- Add all --config switches for this project. This is also called
1232 -- for aggregate projects.
1234 -------------------------------------
1235 -- Add_Config_Switches_For_Project --
1236 -------------------------------------
1238 procedure Add_Config_Switches_For_Project
1239 (Project
: Project_Id
;
1240 Tree
: Project_Tree_Ref
;
1241 With_State
: in out Integer)
1243 pragma Unreferenced
(With_State
);
1245 Shared
: constant Shared_Project_Tree_Data_Access
:= Tree
.Shared
;
1247 Variable
: Variable_Value
;
1248 Check_Default
: Boolean;
1250 List
: String_List_Id
;
1251 Elem
: String_Element
;
1254 if Might_Have_Sources
(Project
) then
1256 Value_Of
(Name_Languages
, Project
.Decl
.Attributes
, Shared
);
1258 if Variable
= Nil_Variable_Value
or else Variable
.Default
then
1260 -- Languages is not declared. If it is not an extending
1261 -- project, or if it extends a project with no Languages,
1262 -- check for Default_Language.
1264 Check_Default
:= Project
.Extends
= No_Project
;
1266 if not Check_Default
then
1270 Project
.Extends
.Decl
.Attributes
,
1273 Variable
/= Nil_Variable_Value
1274 and then Variable
.Values
= Nil_String
;
1277 if Check_Default
then
1280 (Name_Default_Language
,
1281 Project
.Decl
.Attributes
,
1284 if Variable
/= Nil_Variable_Value
1285 and then not Variable
.Default
1287 Get_Name_String
(Variable
.Value
);
1288 To_Lower
(Name_Buffer
(1 .. Name_Len
));
1290 Language_Htable
.Set
(Lang
, Lang
);
1292 -- If no default language is declared, default to Ada
1295 Language_Htable
.Set
(Name_Ada
, Name_Ada
);
1299 elsif Variable
.Values
/= Nil_String
then
1301 -- Attribute Languages is declared with a non empty list:
1302 -- put all the languages in Language_HTable.
1304 List
:= Variable
.Values
;
1305 while List
/= Nil_String
loop
1306 Elem
:= Shared
.String_Elements
.Table
(List
);
1308 Get_Name_String
(Elem
.Value
);
1309 To_Lower
(Name_Buffer
(1 .. Name_Len
));
1311 Language_Htable
.Set
(Lang
, Lang
);
1317 end Add_Config_Switches_For_Project
;
1319 procedure For_Every_Imported_Project
is new For_Every_Project_Imported
1320 (State
=> Integer, Action
=> Add_Config_Switches_For_Project
);
1321 -- Document this procedure ???
1327 Result
: Argument_List_Access
;
1328 Variable
: Variable_Value
;
1329 Dummy
: Integer := 0;
1331 -- Start of processing for Get_Config_Switches
1334 For_Every_Imported_Project
1336 Tree
=> Project_Tree
,
1337 With_State
=> Dummy
,
1338 Include_Aggregated
=> True);
1340 Name
:= Language_Htable
.Get_First
;
1342 while Name
/= No_Name
loop
1344 Name
:= Language_Htable
.Get_Next
;
1347 Result
:= new String_List
(1 .. Count
);
1350 Name
:= Language_Htable
.Get_First
;
1351 while Name
/= No_Name
loop
1353 -- Check if IDE'Compiler_Command is declared for the language.
1354 -- If it is, use its value to invoke gprconfig.
1359 Attribute_Or_Array_Name
=> Name_Compiler_Command
,
1362 Force_Lower_Case_Index
=> True);
1365 Config_Command
: constant String :=
1366 "--config=" & Get_Name_String
(Name
);
1368 Runtime_Name
: constant String := Runtime_Name_For
(Name
);
1371 -- In CodePeer mode, we do not take into account any compiler
1372 -- command from the package IDE.
1375 or else Variable
= Nil_Variable_Value
1376 or else Length_Of_Name
(Variable
.Value
) = 0
1379 new String'(Config_Command & ",," & Runtime_Name);
1382 At_Least_One_Compiler_Command := True;
1385 Compiler_Command : constant String :=
1386 Get_Name_String (Variable.Value);
1389 if Is_Absolute_Path (Compiler_Command) then
1392 (Config_Command
& ",," & Runtime_Name
& ","
1393 & Containing_Directory
(Compiler_Command
) & ","
1394 & Simple_Name
(Compiler_Command
));
1398 (Config_Command & ",," & Runtime_Name & ",,"
1399 & Compiler_Command);
1406 Name := Language_Htable.Get_Next;
1410 end Get_Config_Switches;
1412 ------------------------
1413 -- Might_Have_Sources --
1414 ------------------------
1416 function Might_Have_Sources (Project : Project_Id) return Boolean is
1417 Variable : Variable_Value;
1421 Value_Of (Name_Source_Dirs, Project.Decl.Attributes, Shared);
1423 if Variable = Nil_Variable_Value
1424 or else Variable.Default
1425 or else Variable.Values /= Nil_String
1428 Value_Of (Name_Source_Files, Project.Decl.Attributes, Shared);
1429 return Variable = Nil_Variable_Value
1430 or else Variable.Default
1431 or else Variable.Values /= Nil_String;
1436 end Might_Have_Sources;
1441 Config_Project_Node : Project_Node_Id := Empty_Node;
1443 -- Start of processing for Get_Or_Create_Configuration_File
1446 pragma Assert (Prj.Env.Is_Initialized (Env.Project_Path));
1448 Free (Config_File_Path);
1449 Config := No_Project;
1452 Get_Project_Runtimes;
1453 Check_Builder_Switches;
1455 -- Do not attempt to find a configuration project file when
1456 -- Config_File_Name is No_Configuration_File.
1458 if Config_File_Name = No_Configuration_File then
1459 Config_File_Path := null;
1462 if Conf_File_Name'Length > 0 then
1463 Config_File_Path := Locate_Config_File (Conf_File_Name.all);
1465 Config_File_Path := Locate_Config_File (Default_File_Name);
1468 if Config_File_Path = null then
1469 if not Allow_Automatic_Generation
1470 and then Conf_File_Name'Length > 0
1472 Raise_Invalid_Config
1473 ("could not locate main configuration project "
1474 & Conf_File_Name.all);
1479 Automatically_Generated :=
1480 Allow_Automatic_Generation and then Config_File_Path = null;
1482 <<Process_Config_File>>
1484 if Automatically_Generated then
1486 -- This might raise an Invalid_Config exception
1490 -- If the config file is not auto-generated, warn if there is any --RTS
1491 -- switch, but not when the config file is generated in memory.
1494 and then RTS_Languages.Get_First /= No_Name
1495 and then Opt.Warning_Mode /= Opt.Suppress
1496 and then On_Load_Config = null
1500 "runtimes are taken into account only in auto-configuration");
1503 -- Parse the configuration file
1505 if Verbose_Mode and then Config_File_Path /= null then
1506 Write_Str ("Checking configuration ");
1507 Write_Line (Config_File_Path.all);
1510 if Config_File_Path /= null then
1512 (In_Tree => Project_Node_Tree,
1513 Project => Config_Project_Node,
1514 Project_File_Name => Config_File_Path.all,
1515 Errout_Handling => Prj.Part.Finalize_If_Error,
1516 Packages_To_Check => Packages_To_Check,
1517 Current_Directory => Current_Directory,
1518 Is_Config_File => True,
1521 Config_Project_Node := Empty_Node;
1524 if On_Load_Config /= null then
1526 (Config_File => Config_Project_Node,
1527 Project_Node_Tree => Project_Node_Tree);
1530 if Config_Project_Node /= Empty_Node then
1531 Prj.Proc.Process_Project_Tree_Phase_1
1532 (In_Tree => Project_Tree,
1534 Packages_To_Check => Packages_To_Check,
1536 From_Project_Node => Config_Project_Node,
1537 From_Project_Node_Tree => Project_Node_Tree,
1539 Reset_Tree => False,
1540 On_New_Tree_Loaded => null);
1543 if Config_Project_Node = Empty_Node or else Config = No_Project then
1544 Raise_Invalid_Config
1545 ("processing of configuration project """
1546 & Config_File_Path.all & """ failed");
1549 -- Check that the target of the configuration file is the one the user
1550 -- specified on the command line. We do not need to check that when in
1551 -- auto-conf mode, since the appropriate target was passed to gprconfig.
1553 if not Automatically_Generated
1556 (Config, Autoconf_Specified, Project_Tree, Selected_Target.all)
1558 Automatically_Generated := True;
1559 goto Process_Config_File;
1561 end Get_Or_Create_Configuration_File;
1563 ------------------------
1564 -- Locate_Config_File --
1565 ------------------------
1567 function Locate_Config_File (Name : String) return String_Access is
1568 Prefix_Path : constant String := Executable_Prefix_Path;
1570 if Prefix_Path'Length /= 0 then
1571 return Locate_Regular_File
1573 "." & Path_Separator &
1574 Prefix_Path & "share" & Directory_Separator & "gpr");
1576 return Locate_Regular_File (Name, ".");
1578 end Locate_Config_File;
1580 ------------------------------------
1581 -- Parse_Project_And_Apply_Config --
1582 ------------------------------------
1584 procedure Parse_Project_And_Apply_Config
1585 (Main_Project : out Prj.Project_Id;
1586 User_Project_Node : out Prj.Tree.Project_Node_Id;
1587 Config_File_Name : String := "";
1588 Autoconf_Specified : Boolean;
1589 Project_File_Name : String;
1590 Project_Tree : Prj.Project_Tree_Ref;
1591 Project_Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
1592 Env : in out Prj.Tree.Environment;
1593 Packages_To_Check : String_List_Access;
1594 Allow_Automatic_Generation : Boolean := True;
1595 Automatically_Generated : out Boolean;
1596 Config_File_Path : out String_Access;
1597 Target_Name : String := "";
1598 Normalized_Hostname : String;
1599 On_Load_Config : Config_File_Hook := null;
1600 Implicit_Project : Boolean := False;
1601 On_New_Tree_Loaded : Prj.Proc.Tree_Loaded_Callback := null)
1603 Success : Boolean := False;
1604 Target_Try_Again : Boolean := True;
1605 Config_Try_Again : Boolean;
1607 Finalization : Prj.Part.Errout_Mode := Prj.Part.Always_Finalize;
1609 S : State := No_State;
1611 Conf_File_Name : String_Access := new String'(Config_File_Name
);
1613 procedure Add_Directory
(Dir
: String);
1614 -- Add a directory at the end of the Project Path
1616 Auto_Generated
: Boolean;
1622 procedure Add_Directory
(Dir
: String) is
1624 if Opt
.Verbose_Mode
then
1625 Write_Line
(" Adding directory """ & Dir
& """");
1628 Prj
.Env
.Add_Directories
(Env
.Project_Path
, Dir
);
1632 pragma Assert
(Prj
.Env
.Is_Initialized
(Env
.Project_Path
));
1634 -- Start with ignoring missing withed projects
1636 Set_Ignore_Missing_With
(Env
.Flags
, True);
1638 -- Note: If in fact the config file is automatically generated, then
1639 -- Automatically_Generated will be set to True after invocation of
1640 -- Process_Project_And_Apply_Config.
1642 Automatically_Generated
:= False;
1644 -- Record Target_Value and Target_Origin
1646 if Target_Name
= "" then
1647 Opt
.Target_Value
:= new String'(Normalized_Hostname);
1648 Opt.Target_Origin := Default;
1650 Opt.Target_Value := new String'(Target_Name
);
1651 Opt
.Target_Origin
:= Specified
;
1656 -- Parse the user project tree
1658 Project_Node_Tree
.Incomplete_With
:= False;
1659 Env
.Flags
.Incomplete_Withs
:= False;
1660 Prj
.Initialize
(Project_Tree
);
1662 Main_Project
:= No_Project
;
1665 (In_Tree
=> Project_Node_Tree
,
1666 Project
=> User_Project_Node
,
1667 Project_File_Name
=> Project_File_Name
,
1668 Errout_Handling
=> Finalization
,
1669 Packages_To_Check
=> Packages_To_Check
,
1670 Current_Directory
=> Current_Directory
,
1671 Is_Config_File
=> False,
1673 Implicit_Project
=> Implicit_Project
);
1675 Finalization
:= Prj
.Part
.Finalize_If_Error
;
1677 if User_Project_Node
= Empty_Node
then
1681 -- If --target was not specified on the command line, then do Phase 1 to
1682 -- check if attribute Target is declared in the main project.
1684 if Opt
.Target_Origin
/= Specified
then
1685 Main_Project
:= No_Project
;
1686 Process_Project_Tree_Phase_1
1687 (In_Tree
=> Project_Tree
,
1688 Project
=> Main_Project
,
1689 Packages_To_Check
=> Packages_To_Check
,
1691 From_Project_Node
=> User_Project_Node
,
1692 From_Project_Node_Tree
=> Project_Node_Tree
,
1695 On_New_Tree_Loaded
=> On_New_Tree_Loaded
);
1698 Main_Project
:= No_Project
;
1703 Variable
: constant Variable_Value
:=
1706 Main_Project
.Decl
.Attributes
,
1707 Project_Tree
.Shared
);
1709 if Variable
/= Nil_Variable_Value
1710 and then not Variable
.Default
1712 Get_Name_String
(Variable
.Value
) /= Opt
.Target_Value
.all
1714 if Target_Try_Again
then
1716 new String'(Get_Name_String (Variable.Value));
1717 Target_Try_Again := False;
1723 "inconsistent value of attribute Target");
1729 -- If there are missing withed projects, the projects will be parsed
1730 -- again after the project path is extended with directories rooted
1731 -- at the compiler roots.
1733 Config_Try_Again := Project_Node_Tree.Incomplete_With;
1735 Process_Project_And_Apply_Config
1736 (Main_Project => Main_Project,
1737 User_Project_Node => User_Project_Node,
1738 Config_File_Name => Conf_File_Name.all,
1739 Autoconf_Specified => Autoconf_Specified,
1740 Project_Tree => Project_Tree,
1741 Project_Node_Tree => Project_Node_Tree,
1743 Packages_To_Check => Packages_To_Check,
1744 Allow_Automatic_Generation => Allow_Automatic_Generation,
1745 Automatically_Generated => Auto_Generated,
1746 Config_File_Path => Config_File_Path,
1747 Target_Name => Target_Name,
1748 Normalized_Hostname => Normalized_Hostname,
1749 On_Load_Config => On_Load_Config,
1750 On_New_Tree_Loaded => On_New_Tree_Loaded,
1751 Do_Phase_1 => Opt.Target_Origin = Specified);
1753 if Auto_Generated then
1754 Automatically_Generated := True;
1757 -- Exit if there was an error. Otherwise, if Config_Try_Again is True,
1758 -- update the project path and try again.
1760 if Main_Project /= No_Project and then Config_Try_Again then
1761 Set_Ignore_Missing_With (Env.Flags, False);
1763 if Config_File_Path /= null then
1764 Conf_File_Name := new String'(Config_File_Path
.all);
1767 -- For the second time the project files are parsed, the warning for
1768 -- --RTS= being only taken into account in auto-configuration are
1769 -- suppressed, as we are no longer in auto-configuration.
1771 Warn_For_RTS
:= False;
1773 -- Add the default directories corresponding to the compilers
1776 (By
=> Main_Project
,
1777 Tree
=> Project_Tree
,
1779 Include_Aggregated
=> True,
1780 Imported_First
=> False);
1783 Compiler_Root
: Compiler_Root_Ptr
;
1784 Prefix
: String_Access
;
1785 Runtime_Root
: Runtime_Root_Ptr
;
1786 Path_Value
: constant String_Access
:= Getenv
("PATH");
1789 if Opt
.Verbose_Mode
then
1790 Write_Line
("Setting the default project search directories");
1792 if Prj
.Current_Verbosity
= High
then
1793 if Path_Value
= null or else Path_Value
'Length = 0 then
1794 Write_Line
("No environment variable PATH");
1797 Write_Line
("PATH =");
1798 Write_Line
(" " & Path_Value
.all);
1803 -- Reorder the compiler roots in the PATH order
1805 if First_Compiler_Root
/= null
1806 and then First_Compiler_Root
.Next
/= null
1809 Pred
: Compiler_Root_Ptr
;
1810 First_New_Comp
: Compiler_Root_Ptr
:= null;
1811 New_Comp
: Compiler_Root_Ptr
:= null;
1812 First
: Positive := Path_Value
'First;
1814 Path_Last
: Positive;
1816 while First
<= Path_Value
'Last loop
1819 if Path_Value
(First
) /= Path_Separator
then
1820 while Last
< Path_Value
'Last
1821 and then Path_Value
(Last
+ 1) /= Path_Separator
1827 while Path_Last
> First
1829 Path_Value
(Path_Last
) = Directory_Separator
1831 Path_Last
:= Path_Last
- 1;
1834 if Path_Last
> First
+ 4
1836 Path_Value
(Path_Last
- 2 .. Path_Last
) = "bin"
1838 Path_Value
(Path_Last
- 3) = Directory_Separator
1840 Path_Last
:= Path_Last
- 4;
1842 Compiler_Root
:= First_Compiler_Root
;
1843 while Compiler_Root
/= null
1844 and then Compiler_Root
.Root
.all /=
1845 Path_Value
(First
.. Path_Last
)
1847 Pred
:= Compiler_Root
;
1848 Compiler_Root
:= Compiler_Root
.Next
;
1851 if Compiler_Root
/= null then
1853 First_Compiler_Root
:=
1854 First_Compiler_Root
.Next
;
1856 Pred
.Next
:= Compiler_Root
.Next
;
1859 if First_New_Comp
= null then
1860 First_New_Comp
:= Compiler_Root
;
1862 New_Comp
.Next
:= Compiler_Root
;
1865 New_Comp
:= Compiler_Root
;
1866 New_Comp
.Next
:= null;
1874 if First_New_Comp
/= null then
1875 New_Comp
.Next
:= First_Compiler_Root
;
1876 First_Compiler_Root
:= First_New_Comp
;
1881 -- Now that the compiler roots are in a correct order, add the
1882 -- directories corresponding to these compiler roots in the
1885 Compiler_Root
:= First_Compiler_Root
;
1886 while Compiler_Root
/= null loop
1887 Prefix
:= Compiler_Root
.Root
;
1889 Runtime_Root
:= Compiler_Root
.Runtimes
;
1890 while Runtime_Root
/= null loop
1892 (Runtime_Root
.Root
.all &
1893 Directory_Separator
&
1895 Directory_Separator
&
1898 (Runtime_Root
.Root
.all &
1899 Directory_Separator
&
1901 Directory_Separator
&
1903 Runtime_Root
:= Runtime_Root
.Next
;
1908 Directory_Separator
&
1909 Opt
.Target_Value
.all &
1910 Directory_Separator
&
1912 Directory_Separator
&
1916 Directory_Separator
&
1917 Opt
.Target_Value
.all &
1918 Directory_Separator
&
1920 Directory_Separator
&
1924 Directory_Separator
&
1926 Directory_Separator
&
1930 Directory_Separator
&
1932 Directory_Separator
&
1934 Compiler_Root
:= Compiler_Root
.Next
;
1938 -- And parse again the project files. There will be no missing
1939 -- withed projects, as Ignore_Missing_With is set to False in
1940 -- the environment flags, so there is no risk of endless loop here.
1944 end Parse_Project_And_Apply_Config
;
1946 --------------------------------------
1947 -- Process_Project_And_Apply_Config --
1948 --------------------------------------
1950 procedure Process_Project_And_Apply_Config
1951 (Main_Project
: out Prj
.Project_Id
;
1952 User_Project_Node
: Prj
.Tree
.Project_Node_Id
;
1953 Config_File_Name
: String := "";
1954 Autoconf_Specified
: Boolean;
1955 Project_Tree
: Prj
.Project_Tree_Ref
;
1956 Project_Node_Tree
: Prj
.Tree
.Project_Node_Tree_Ref
;
1957 Env
: in out Prj
.Tree
.Environment
;
1958 Packages_To_Check
: String_List_Access
;
1959 Allow_Automatic_Generation
: Boolean := True;
1960 Automatically_Generated
: out Boolean;
1961 Config_File_Path
: out String_Access
;
1962 Target_Name
: String := "";
1963 Normalized_Hostname
: String;
1964 On_Load_Config
: Config_File_Hook
:= null;
1965 Reset_Tree
: Boolean := True;
1966 On_New_Tree_Loaded
: Prj
.Proc
.Tree_Loaded_Callback
:= null;
1967 Do_Phase_1
: Boolean := True)
1969 Shared
: constant Shared_Project_Tree_Data_Access
:=
1970 Project_Tree
.Shared
;
1971 Main_Config_Project
: Project_Id
;
1974 Conf_Project
: Project_Id
:= No_Project
;
1975 -- The object directory of this project is used to store the config
1976 -- project file in auto-configuration. Set by Check_Project below.
1978 procedure Check_Project
(Project
: Project_Id
);
1979 -- Look for a non aggregate project. If one is found, put its project Id
1986 procedure Check_Project
(Project
: Project_Id
) is
1988 if Project
.Qualifier
= Aggregate
1990 Project
.Qualifier
= Aggregate_Library
1993 List
: Aggregated_Project_List
:= Project
.Aggregated_Projects
;
1996 -- Look for a non aggregate project until one is found
1998 while Conf_Project
= No_Project
and then List
/= null loop
1999 Check_Project
(List
.Project
);
2005 Conf_Project
:= Project
;
2009 -- Start of processing for Process_Project_And_Apply_Config
2012 Automatically_Generated
:= False;
2015 Main_Project
:= No_Project
;
2016 Process_Project_Tree_Phase_1
2017 (In_Tree
=> Project_Tree
,
2018 Project
=> Main_Project
,
2019 Packages_To_Check
=> Packages_To_Check
,
2021 From_Project_Node
=> User_Project_Node
,
2022 From_Project_Node_Tree
=> Project_Node_Tree
,
2024 Reset_Tree
=> Reset_Tree
,
2025 On_New_Tree_Loaded
=> On_New_Tree_Loaded
);
2028 Main_Project
:= No_Project
;
2033 if Project_Tree
.Source_Info_File_Name
/= null then
2034 if not Is_Absolute_Path
(Project_Tree
.Source_Info_File_Name
.all) then
2036 Obj_Dir
: constant Variable_Value
:=
2039 Main_Project
.Decl
.Attributes
,
2043 if Obj_Dir
= Nil_Variable_Value
or else Obj_Dir
.Default
then
2044 Get_Name_String
(Main_Project
.Directory
.Display_Name
);
2047 if Is_Absolute_Path
(Get_Name_String
(Obj_Dir
.Value
)) then
2048 Get_Name_String
(Obj_Dir
.Value
);
2052 Add_Str_To_Name_Buffer
2053 (Get_Name_String
(Main_Project
.Directory
.Display_Name
));
2054 Add_Str_To_Name_Buffer
(Get_Name_String
(Obj_Dir
.Value
));
2058 Add_Char_To_Name_Buffer
(Directory_Separator
);
2059 Add_Str_To_Name_Buffer
(Project_Tree
.Source_Info_File_Name
.all);
2060 Free
(Project_Tree
.Source_Info_File_Name
);
2061 Project_Tree
.Source_Info_File_Name
:=
2062 new String'(Name_Buffer (1 .. Name_Len));
2066 Read_Source_Info_File (Project_Tree);
2069 -- Get the first project that is not an aggregate project or an
2070 -- aggregate library project. The object directory of this project will
2071 -- be used to store the config project file in auto-configuration.
2073 Check_Project (Main_Project);
2075 -- Fail if there is only aggregate projects and aggregate library
2076 -- projects in the project tree.
2078 if Conf_Project = No_Project then
2079 Raise_Invalid_Config ("there are no non-aggregate projects");
2082 -- Find configuration file
2084 Get_Or_Create_Configuration_File
2085 (Config => Main_Config_Project,
2086 Project => Main_Project,
2087 Conf_Project => Conf_Project,
2088 Project_Tree => Project_Tree,
2089 Project_Node_Tree => Project_Node_Tree,
2091 Allow_Automatic_Generation => Allow_Automatic_Generation,
2092 Config_File_Name => Config_File_Name,
2093 Autoconf_Specified => Autoconf_Specified,
2094 Target_Name => Target_Name,
2095 Normalized_Hostname => Normalized_Hostname,
2096 Packages_To_Check => Packages_To_Check,
2097 Config_File_Path => Config_File_Path,
2098 Automatically_Generated => Automatically_Generated,
2099 On_Load_Config => On_Load_Config);
2101 Apply_Config_File (Main_Config_Project, Project_Tree);
2103 -- Finish processing the user's project
2105 Prj.Proc.Process_Project_Tree_Phase_2
2106 (In_Tree => Project_Tree,
2107 Project => Main_Project,
2109 From_Project_Node => User_Project_Node,
2110 From_Project_Node_Tree => Project_Node_Tree,
2114 if Project_Tree.Source_Info_File_Name /= null
2115 and then not Project_Tree.Source_Info_File_Exists
2117 Write_Source_Info_File (Project_Tree);
2121 Main_Project := No_Project;
2123 end Process_Project_And_Apply_Config;
2125 --------------------------
2126 -- Raise_Invalid_Config --
2127 --------------------------
2129 procedure Raise_Invalid_Config (Msg : String) is
2131 Raise_Exception (Invalid_Config'Identity, Msg);
2132 end Raise_Invalid_Config;
2134 ----------------------
2135 -- Runtime_Name_For --
2136 ----------------------
2138 function Runtime_Name_For (Language : Name_Id) return String is
2140 if RTS_Languages.Get (Language) /= No_Name then
2141 return Get_Name_String (RTS_Languages.Get (Language));
2145 end Runtime_Name_For;
2147 --------------------------
2148 -- Runtime_Name_Set_For --
2149 --------------------------
2151 function Runtime_Name_Set_For (Language : Name_Id) return Boolean is
2153 return RTS_Languages.Get (Language) /= No_Name;
2154 end Runtime_Name_Set_For;
2156 ---------------------
2157 -- Set_Runtime_For --
2158 ---------------------
2160 procedure Set_Runtime_For (Language : Name_Id; RTS_Name : String) is
2162 Name_Len := RTS_Name'Length;
2163 Name_Buffer (1 .. Name_Len) := RTS_Name;
2164 RTS_Languages.Set (Language, Name_Find);
2165 end Set_Runtime_For;
2167 ----------------------------
2168 -- Look_For_Project_Paths --
2169 ----------------------------
2171 procedure Look_For_Project_Paths
2172 (Project : Project_Id;
2173 Tree : Project_Tree_Ref;
2174 With_State : in out State)
2176 Lang_Id : Language_Ptr;
2177 Compiler_Root : Compiler_Root_Ptr;
2178 Runtime_Root : Runtime_Root_Ptr;
2179 Comp_Driver : String_Access;
2180 Comp_Dir : String_Access;
2181 Prefix : String_Access;
2183 pragma Unreferenced (Tree);
2186 With_State := No_State;
2188 Lang_Id := Project.Languages;
2189 while Lang_Id /= No_Language_Index loop
2190 if Lang_Id.Config.Compiler_Driver /= No_File then
2193 (Get_Name_String
(Lang_Id
.Config
.Compiler_Driver
));
2195 -- Get the absolute path of the compiler driver
2197 if not Is_Absolute_Path
(Comp_Driver
.all) then
2198 Comp_Driver
:= Locate_Exec_On_Path
(Comp_Driver
.all);
2201 if Comp_Driver
/= null and then Comp_Driver
'Length > 0 then
2204 (Containing_Directory (Comp_Driver.all));
2206 -- Consider only the compiler drivers that are in "bin"
2209 if Simple_Name (Comp_Dir.all) = "bin" then
2211 new String'(Containing_Directory
(Comp_Dir
.all));
2213 -- Check if the compiler root is already in the list. If it
2214 -- is not, add it to the list.
2216 Compiler_Root
:= First_Compiler_Root
;
2217 while Compiler_Root
/= null loop
2218 exit when Prefix
.all = Compiler_Root
.Root
.all;
2219 Compiler_Root
:= Compiler_Root
.Next
;
2222 if Compiler_Root
= null then
2223 First_Compiler_Root
:=
2224 new Compiler_Root_Data
'
2227 Next => First_Compiler_Root);
2228 Compiler_Root := First_Compiler_Root;
2231 -- If there is a runtime for this compiler, check if it is
2232 -- recorded with the compiler root. If it is not, record
2236 Runtime : constant String :=
2237 Runtime_Name_For (Lang_Id.Name);
2238 Root : String_Access;
2241 if Runtime'Length > 0 then
2242 if Is_Absolute_Path (Runtime) then
2243 Root := new String'(Runtime
);
2249 Directory_Separator &
2250 Opt.Target_Value.all &
2251 Directory_Separator &
2255 Runtime_Root := Compiler_Root.Runtimes;
2256 while Runtime_Root /= null loop
2257 exit when Root.all = Runtime_Root.Root.all;
2258 Runtime_Root := Runtime_Root.Next;
2261 if Runtime_Root = null then
2262 Compiler_Root.Runtimes :=
2263 new Runtime_Root_Data'
2265 Next
=> Compiler_Root
.Runtimes
);
2273 Lang_Id
:= Lang_Id
.Next
;
2275 end Look_For_Project_Paths
;