1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2016, AdaCore --
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 ------------------------------------------------------------------------------
27 with Gnatvsn
; use Gnatvsn
;
28 with Makeutl
; use Makeutl
;
29 with MLib
.Fil
; use MLib
.Fil
;
30 with MLib
.Tgt
; use MLib
.Tgt
;
31 with MLib
.Utl
; use MLib
.Utl
;
33 with Output
; use Output
;
34 with Prj
.Com
; use Prj
.Com
;
35 with Prj
.Env
; use Prj
.Env
;
36 with Prj
.Util
; use Prj
.Util
;
38 with Snames
; use Snames
;
39 with Switch
; use Switch
;
42 with Types
; use Types
;
44 with Ada
.Characters
.Handling
;
46 with GNAT
.Directory_Operations
; use GNAT
.Directory_Operations
;
48 with Interfaces
.C_Streams
; use Interfaces
.C_Streams
;
49 with System
; use System
;
50 with System
.Case_Util
; use System
.Case_Util
;
52 package body MLib
.Prj
is
54 Prj_Add_Obj_Files
: Types
.Int
;
55 pragma Import
(C
, Prj_Add_Obj_Files
, "__gnat_prj_add_obj_files");
56 Add_Object_Files
: constant Boolean := Prj_Add_Obj_Files
/= 0;
57 -- Indicates if object files in pragmas Linker_Options (found in the
58 -- binder generated file) should be taken when linking a stand-alone
59 -- library. False for Windows, True for other platforms.
61 ALI_Suffix
: constant String := ".ali";
63 B_Start
: constant String := "b~";
64 -- Prefix of bind file
66 S_Osinte_Ads
: File_Name_Type
:= No_File
;
67 -- Name_Id for "s-osinte.ads"
69 S_Dec_Ads
: File_Name_Type
:= No_File
;
70 -- Name_Id for "dec.ads"
72 Arguments
: String_List_Access
:= No_Argument
;
73 -- Used to accumulate arguments for the invocation of gnatbind and of the
74 -- compiler. Also used to collect the interface ALI when copying the ALI
75 -- files to the library directory.
77 Argument_Number
: Natural := 0;
78 -- Index of the last argument in Arguments
80 Initial_Argument_Max
: constant := 10;
81 -- Where does the magic constant 10 come from???
83 No_Main_String
: aliased String := "-n";
84 No_Main
: constant String_Access
:= No_Main_String
'Access;
86 Output_Switch_String
: aliased String := "-o";
87 Output_Switch
: constant String_Access
:=
88 Output_Switch_String
'Access;
90 Compile_Switch_String
: aliased String := "-c";
91 Compile_Switch
: constant String_Access
:=
92 Compile_Switch_String
'Access;
94 No_Warning_String
: aliased String := "-gnatws";
95 No_Warning
: constant String_Access
:= No_Warning_String
'Access;
97 Auto_Initialize
: constant String := "-a";
99 -- List of objects to put inside the library
101 Object_Files
: Argument_List_Access
;
103 package Objects
is new Table
.Table
104 (Table_Name
=> "Mlib.Prj.Objects",
105 Table_Component_Type
=> String_Access
,
106 Table_Index_Type
=> Natural,
107 Table_Low_Bound
=> 1,
109 Table_Increment
=> 100);
111 package Objects_Htable
is new GNAT
.HTable
.Simple_HTable
112 (Header_Num
=> Header_Num
,
121 Ali_Files
: Argument_List_Access
;
123 package ALIs
is new Table
.Table
124 (Table_Name
=> "Mlib.Prj.Alis",
125 Table_Component_Type
=> String_Access
,
126 Table_Index_Type
=> Natural,
127 Table_Low_Bound
=> 1,
129 Table_Increment
=> 100);
131 -- List of options set in the command line
133 Options
: Argument_List_Access
;
135 package Opts
is new Table
.Table
136 (Table_Name
=> "Mlib.Prj.Opts",
137 Table_Component_Type
=> String_Access
,
138 Table_Index_Type
=> Natural,
139 Table_Low_Bound
=> 1,
141 Table_Increment
=> 100);
143 -- All the ALI file in the library
145 package Library_ALIs
is new GNAT
.HTable
.Simple_HTable
146 (Header_Num
=> Header_Num
,
149 Key
=> File_Name_Type
,
153 -- The ALI files in the interface sets
155 package Interface_ALIs
is new GNAT
.HTable
.Simple_HTable
156 (Header_Num
=> Header_Num
,
159 Key
=> File_Name_Type
,
163 -- The ALI files that have been processed to check if the corresponding
164 -- library unit is in the interface set.
166 package Processed_ALIs
is new GNAT
.HTable
.Simple_HTable
167 (Header_Num
=> Header_Num
,
170 Key
=> File_Name_Type
,
174 -- The projects imported directly or indirectly
176 package Processed_Projects
is new GNAT
.HTable
.Simple_HTable
177 (Header_Num
=> Header_Num
,
184 -- The library projects imported directly or indirectly
186 package Library_Projs
is new Table
.Table
(
187 Table_Component_Type
=> Project_Id
,
188 Table_Index_Type
=> Integer,
189 Table_Low_Bound
=> 1,
191 Table_Increment
=> 10,
192 Table_Name
=> "Make.Library_Projs");
194 type Build_Mode_State
is (None
, Static
, Dynamic
, Relocatable
);
196 procedure Add_Argument
(S
: String);
197 -- Add one argument to Arguments array, if array is full, double its size
199 function ALI_File_Name
(Source
: String) return String;
200 -- Return the ALI file name corresponding to a source
202 procedure Check
(Filename
: String);
203 -- Check if filename is a regular file. Fail if it is not
205 procedure Check_Context
;
206 -- Check each object files in table Object_Files
207 -- Fail if any of them is not a regular file
209 procedure Copy_Interface_Sources
210 (For_Project
: Project_Id
;
211 In_Tree
: Project_Tree_Ref
;
212 Interfaces
: Argument_List
;
213 To_Dir
: Path_Name_Type
);
214 -- Copy the interface sources of a SAL to directory To_Dir
216 procedure Display
(Executable
: String);
217 -- Display invocation of gnatbind and of the compiler with the arguments
218 -- in Arguments, except when Quiet_Output is True.
220 function Index
(S
, Pattern
: String) return Natural;
221 -- Return the last occurrence of Pattern in S, or 0 if none
223 procedure Process_Binder_File
(Name
: String);
224 -- For Stand-Alone libraries, get the Linker Options in the binder
227 procedure Reset_Tables
;
228 -- Make sure that all the above tables are empty
229 -- (Objects, Ali_Files, Options).
231 function SALs_Use_Constructors
return Boolean;
232 -- Indicate if Stand-Alone Libraries are automatically initialized using
233 -- the constructor mechanism.
239 procedure Add_Argument
(S
: String) is
241 if Argument_Number
= Arguments
'Last then
243 New_Args
: constant String_List_Access
:=
244 new String_List
(1 .. 2 * Arguments
'Last);
247 -- Copy the String_Accesses and set them to null in Arguments
248 -- so that they will not be deallocated by the call to
251 New_Args
(Arguments
'Range) := Arguments
.all;
252 Arguments
.all := (others => null);
254 Arguments
:= New_Args
;
258 Argument_Number
:= Argument_Number
+ 1;
259 Arguments
(Argument_Number
) := new String'(S);
266 function ALI_File_Name (Source : String) return String is
268 -- If the source name has an extension, then replace it with
271 for Index in reverse Source'First + 1 .. Source'Last loop
272 if Source (Index) = '.' then
273 return Source (Source'First .. Index - 1) & ALI_Suffix;
277 -- If there is no dot, or if it is the first character, just add the
280 return Source & ALI_Suffix;
287 procedure Build_Library
288 (For_Project : Project_Id;
289 In_Tree : Project_Tree_Ref;
291 Gnatbind_Path : String_Access;
293 Gcc_Path : String_Access;
294 Bind : Boolean := True;
295 Link : Boolean := True)
297 Maximum_Size : Integer;
298 pragma Import (C, Maximum_Size, "__gnat_link_max");
299 -- Maximum number of bytes to put in an invocation of gnatbind
302 -- The number of bytes for the invocation of gnatbind
304 Warning_For_Library : Boolean := False;
305 -- Set True for first warning for a unit missing from the interface set
307 Current_Proj : Project_Id;
309 Libgnarl_Needed : Yes_No_Unknown := For_Project.Libgnarl_Needed;
310 -- Set True if library needs to be linked with libgnarl
312 Object_Directory_Path : constant String :=
314 (For_Project.Object_Directory.Display_Name);
316 Standalone : constant Boolean := For_Project.Standalone_Library /= No;
318 Project_Name : constant String := Get_Name_String (For_Project.Name);
320 Current_Dir : constant String := Get_Current_Dir;
322 Lib_Filename : String_Access;
323 Lib_Dirpath : String_Access;
324 Lib_Version : String_Access := new String'("");
326 The_Build_Mode
: Build_Mode_State
:= None
;
328 Success
: Boolean := False;
330 Library_Options
: Variable_Value
:= Nil_Variable_Value
;
332 Driver_Name
: Name_Id
:= No_Name
;
334 In_Main_Object_Directory
: Boolean := True;
336 Foreign_Sources
: Boolean;
338 Rpath
: String_Access
:= null;
339 -- Allocated only if Path Option is supported
341 Rpath_Last
: Natural := 0;
342 -- Index of last valid character of Rpath
344 Initial_Rpath_Length
: constant := 200;
345 -- Initial size of Rpath, when first allocated
347 Path_Option
: String_Access
:= Linker_Library_Path_Option
;
348 -- If null, Path Option is not supported. Not a constant so that it can
351 First_ALI
: File_Name_Type
:= No_File
;
352 -- Store the ALI file name of a source of the library (the first found)
354 procedure Add_ALI_For
(Source
: File_Name_Type
);
355 -- Add name of the ALI file corresponding to Source to the Arguments
357 procedure Add_Rpath
(Path
: String);
358 -- Add a path name to Rpath
360 function Check_Project
(P
: Project_Id
) return Boolean;
361 -- Returns True if P is For_Project or a project extended by For_Project
363 procedure Check_Libs
(ALI_File
: String; Main_Project
: Boolean);
364 -- Set Libgnarl_Needed if the ALI_File indicates that there is a need
365 -- to link with -lgnarl (this is the case when there is a dependency
368 procedure Process
(The_ALI
: File_Name_Type
);
369 -- Check if the closure of a library unit which is or should be in the
370 -- interface set is also in the interface set. Issue a warning for each
371 -- missing library unit.
373 procedure Process_Imported_Libraries
;
374 -- Add the -L and -l switches for the imported Library Project Files,
375 -- and, if Path Option is supported, the library directory path names
382 procedure Add_ALI_For
(Source
: File_Name_Type
) is
383 ALI
: constant String := ALI_File_Name
(Get_Name_String
(Source
));
384 ALI_Id
: File_Name_Type
;
392 Add_Str_To_Name_Buffer
(S
=> ALI
);
395 -- Add the ALI file name to the library ALIs
398 Library_ALIs
.Set
(ALI_Id
, True);
401 -- Set First_ALI, if not already done
403 if First_ALI
= No_File
then
412 procedure Add_Rpath
(Path
: String) is
422 New_Rpath
: constant String_Access
:=
423 new String (1 .. 2 * Rpath
'Length);
425 New_Rpath
(1 .. Rpath_Last
) := Rpath
(1 .. Rpath_Last
);
430 -- Start of processing for Add_Rpath
433 -- If first path, allocate initial Rpath
436 Rpath
:= new String (1 .. Initial_Rpath_Length
);
440 -- Otherwise, add a path separator between two path names
442 if Rpath_Last
= Rpath
'Last then
446 Rpath_Last
:= Rpath_Last
+ 1;
447 Rpath
(Rpath_Last
) := Path_Separator
;
450 -- Increase Rpath size until it is large enough
452 while Rpath_Last
+ Path
'Length > Rpath
'Last loop
458 Rpath
(Rpath_Last
+ 1 .. Rpath_Last
+ Path
'Length) := Path
;
459 Rpath_Last
:= Rpath_Last
+ Path
'Length;
466 function Check_Project
(P
: Project_Id
) return Boolean is
468 if P
= For_Project
then
471 elsif P
/= No_Project
then
477 while Proj
.Extends
/= No_Project
loop
478 if P
= Proj
.Extends
then
482 Proj
:= Proj
.Extends
;
494 procedure Check_Libs
(ALI_File
: String; Main_Project
: Boolean) is
495 Lib_File
: File_Name_Type
;
496 Text
: Text_Buffer_Ptr
;
500 if Libgnarl_Needed
/= Yes
then
504 Name_Len
:= ALI_File
'Length;
505 Name_Buffer
(1 .. Name_Len
) := ALI_File
;
506 Lib_File
:= Name_Find
;
507 Text
:= Read_Library_Info
(Lib_File
, True);
517 -- Look for s-osinte.ads in the dependencies
519 for Index
in ALI
.ALIs
.Table
(Id
).First_Sdep
..
520 ALI
.ALIs
.Table
(Id
).Last_Sdep
522 if ALI
.Sdep
.Table
(Index
).Sfile
= S_Osinte_Ads
then
523 Libgnarl_Needed
:= Yes
;
526 For_Project
.Libgnarl_Needed
:= Yes
;
539 procedure Process
(The_ALI
: File_Name_Type
) is
540 Text
: Text_Buffer_Ptr
;
542 First_Unit
: ALI
.Unit_Id
;
543 Last_Unit
: ALI
.Unit_Id
;
544 Unit_Data
: Unit_Record
;
545 Afile
: File_Name_Type
;
548 -- Nothing to do if the ALI file has already been processed.
549 -- This happens if an interface imports another interface.
551 if not Processed_ALIs
.Get
(The_ALI
) then
552 Processed_ALIs
.Set
(The_ALI
, True);
553 Text
:= Read_Library_Info
(The_ALI
);
564 if Idread
/= No_ALI_Id
then
565 First_Unit
:= ALI
.ALIs
.Table
(Idread
).First_Unit
;
566 Last_Unit
:= ALI
.ALIs
.Table
(Idread
).Last_Unit
;
568 -- Process both unit (spec and body) if the body is needed
569 -- by the spec (inline or generic). Otherwise, just process
572 if First_Unit
/= Last_Unit
and then
573 not ALI
.Units
.Table
(Last_Unit
).Body_Needed_For_SAL
575 First_Unit
:= Last_Unit
;
578 for Unit
in First_Unit
.. Last_Unit
loop
579 Unit_Data
:= ALI
.Units
.Table
(Unit
);
581 -- Check if each withed unit which is in the library is
582 -- also in the interface set, if it has not yet been
585 for W
in Unit_Data
.First_With
.. Unit_Data
.Last_With
loop
586 Afile
:= Withs
.Table
(W
).Afile
;
588 if Afile
/= No_File
and then Library_ALIs
.Get
(Afile
)
589 and then not Processed_ALIs
.Get
(Afile
)
591 if not Interface_ALIs
.Get
(Afile
) then
592 if not Warning_For_Library
then
593 Write_Str
("Warning: In library project """);
594 Get_Name_String
(Current_Proj
.Name
);
595 To_Mixed
(Name_Buffer
(1 .. Name_Len
));
596 Write_Str
(Name_Buffer
(1 .. Name_Len
));
598 Warning_For_Library
:= True;
601 Write_Str
(" Unit """);
602 Get_Name_String
(Withs
.Table
(W
).Uname
);
603 To_Mixed
(Name_Buffer
(1 .. Name_Len
- 2));
604 Write_Str
(Name_Buffer
(1 .. Name_Len
- 2));
605 Write_Line
(""" is not in the interface set");
606 Write_Str
(" but it is needed by ");
608 case Unit_Data
.Utype
is
610 Write_Str
("the spec of ");
613 Write_Str
("the body of ");
620 Get_Name_String
(Unit_Data
.Uname
);
621 To_Mixed
(Name_Buffer
(1 .. Name_Len
- 2));
622 Write_Str
(Name_Buffer
(1 .. Name_Len
- 2));
626 -- Now, process this unit
637 --------------------------------
638 -- Process_Imported_Libraries --
639 --------------------------------
641 procedure Process_Imported_Libraries
is
642 Current
: Project_Id
;
644 procedure Process_Project
(Project
: Project_Id
);
645 -- Process Project and its imported projects recursively.
646 -- Add any library projects to table Library_Projs.
648 ---------------------
649 -- Process_Project --
650 ---------------------
652 procedure Process_Project
(Project
: Project_Id
) is
653 Imported
: Project_List
;
656 -- Nothing to do if process has already been processed
658 if not Processed_Projects
.Get
(Project
.Name
) then
659 Processed_Projects
.Set
(Project
.Name
, True);
661 -- Call Process_Project recursively for any imported project.
662 -- We first process the imported projects to guarantee that
663 -- we have a proper reverse order for the libraries.
665 Imported
:= Project
.Imported_Projects
;
666 while Imported
/= null loop
667 if Imported
.Project
/= No_Project
then
668 Process_Project
(Imported
.Project
);
671 Imported
:= Imported
.Next
;
674 -- If it is a library project, add it to Library_Projs
676 if Project
/= For_Project
and then Project
.Library
then
677 Library_Projs
.Increment_Last
;
678 Library_Projs
.Table
(Library_Projs
.Last
) := Project
;
680 -- Check if because of this library we need to use libgnarl
682 if Libgnarl_Needed
= Unknown
then
683 if Project
.Libgnarl_Needed
= Unknown
684 and then Project
.Object_Directory
/= No_Path_Information
686 -- Check if libgnarl is needed for this library
689 Object_Dir_Path
: constant String :=
691 (Project
.Object_Directory
.
693 Object_Dir
: Dir_Type
;
694 Filename
: String (1 .. 255);
698 Open
(Object_Dir
, Object_Dir_Path
);
700 -- For all entries in the object directory
703 Read
(Object_Dir
, Filename
, Last
);
706 -- Check if it is an object file
708 if Is_Obj
(Filename
(1 .. Last
)) then
710 Object_Path
: constant String :=
713 Directory_Separator
&
714 Filename
(1 .. Last
));
715 ALI_File
: constant String :=
717 (Object_Path
, "ali");
720 if Is_Regular_File
(ALI_File
) then
722 -- Find out if for this ALI file,
723 -- libgnarl is necessary.
726 (ALI_File
, Main_Project
=> False);
728 if Libgnarl_Needed
= Yes
then
729 Project
.Libgnarl_Needed
:= Yes
;
730 For_Project
.Libgnarl_Needed
:= Yes
;
742 if Project
.Libgnarl_Needed
= Yes
then
743 Libgnarl_Needed
:= Yes
;
744 For_Project
.Libgnarl_Needed
:= Yes
;
751 -- Start of processing for Process_Imported_Libraries
754 -- Build list of library projects imported directly or indirectly,
755 -- in the reverse order.
757 Process_Project
(For_Project
);
759 -- Add the -L and -l switches and, if the Rpath option is supported,
760 -- add the directory to the Rpath. As the library projects are in the
761 -- wrong order, process from the last to the first.
763 for Index
in reverse 1 .. Library_Projs
.Last
loop
764 Current
:= Library_Projs
.Table
(Index
);
766 Get_Name_String
(Current
.Library_Dir
.Display_Name
);
768 Opts
.Table
(Opts
.Last
) :=
769 new String'("-L" & Name_Buffer (1 .. Name_Len));
771 if Path_Option /= null then
772 Add_Rpath (Name_Buffer (1 .. Name_Len));
776 Opts.Table (Opts.Last) :=
777 new String'("-l" & Get_Name_String
(Current
.Library_Name
));
779 end Process_Imported_Libraries
;
781 Path_FD
: File_Descriptor
:= Invalid_FD
;
782 -- Used for setting the source and object paths
784 -- Start of processing for Build_Library
789 -- Fail if project is not a library project
791 if not For_Project
.Library
then
792 Com
.Fail
("project """ & Project_Name
& """ has no library");
795 -- Do not attempt to build the library if it is externally built
797 if For_Project
.Externally_Built
then
801 -- If this is the first time Build_Library is called, get the Name_Id
802 -- of "s-osinte.ads".
804 if S_Osinte_Ads
= No_File
then
806 Add_Str_To_Name_Buffer
("s-osinte.ads");
807 S_Osinte_Ads
:= Name_Find
;
810 if S_Dec_Ads
= No_File
then
812 Add_Str_To_Name_Buffer
("dec.ads");
813 S_Dec_Ads
:= Name_Find
;
816 -- We work in the object directory
818 Change_Dir
(Object_Directory_Path
);
822 -- Call gnatbind only if Bind is True
825 if Gnatbind_Path
= null then
826 Com
.Fail
("unable to locate " & Gnatbind
);
829 if Gcc_Path
= null then
830 Com
.Fail
("unable to locate " & Gcc
);
833 -- Allocate Arguments, if it is the first time we see a standalone
836 if Arguments
= No_Argument
then
837 Arguments
:= new String_List
(1 .. Initial_Argument_Max
);
840 -- Add "-n -o b~<lib>.adb -L<lib>_"
842 Argument_Number
:= 2;
843 Arguments
(1) := No_Main
;
844 Arguments
(2) := Output_Switch
;
847 (B_Start
& Get_Name_String
(For_Project
.Library_Name
) & ".adb");
849 -- Make sure that the init procedure is never "adainit"
851 Get_Name_String
(For_Project
.Library_Name
);
853 if Name_Buffer
(1 .. Name_Len
) = "ada" then
854 Add_Argument
("-Lada_");
857 ("-L" & Get_Name_String
(For_Project
.Library_Name
));
860 if For_Project
.Lib_Auto_Init
and then SALs_Use_Constructors
then
861 Add_Argument
(Auto_Initialize
);
864 -- Check if Binder'Default_Switches ("Ada") is defined. If it is,
865 -- add these switches to call gnatbind.
868 Binder_Package
: constant Package_Id
:=
870 (Name
=> Name_Binder
,
871 In_Packages
=> For_Project
.Decl
.Packages
,
872 Shared
=> In_Tree
.Shared
);
875 if Binder_Package
/= No_Package
then
877 Defaults
: constant Array_Element_Id
:=
879 (Name
=> Name_Default_Switches
,
881 In_Tree
.Shared
.Packages
.Table
882 (Binder_Package
).Decl
.Arrays
,
883 Shared
=> In_Tree
.Shared
);
885 Switches
: Variable_Value
:= Nil_Variable_Value
;
886 Switch
: String_List_Id
:= Nil_String
;
889 if Defaults
/= No_Array_Element
then
894 In_Array
=> Defaults
,
895 Shared
=> In_Tree
.Shared
);
897 if not Switches
.Default
then
898 Switch
:= Switches
.Values
;
900 while Switch
/= Nil_String
loop
903 (In_Tree
.Shared
.String_Elements
.Table
905 Switch
:= In_Tree
.Shared
.String_Elements
.
915 -- Get all the ALI files of the project file. We do that even if
916 -- Bind is False, so that First_ALI is set.
923 Interface_ALIs
.Reset
;
924 Processed_ALIs
.Reset
;
926 Unit
:= Units_Htable
.Get_First
(In_Tree
.Units_HT
);
927 while Unit
/= No_Unit_Index
loop
928 if Unit
.File_Names
(Impl
) /= null
929 and then not Unit
.File_Names
(Impl
).Locally_Removed
931 if Check_Project
(Unit
.File_Names
(Impl
).Project
) then
932 if Unit
.File_Names
(Spec
) = null then
934 -- Add the ALI file only if it is not a subunit
937 Src_Ind
: constant Source_File_Index
:=
938 Sinput
.P
.Load_Project_File
940 (Unit
.File_Names
(Impl
).Path
.Name
));
943 Sinput
.P
.Source_File_Is_Subunit
(Src_Ind
)
945 Add_ALI_For
(Unit
.File_Names
(Impl
).File
);
951 Add_ALI_For
(Unit
.File_Names
(Impl
).File
);
956 elsif Unit
.File_Names
(Spec
) /= null
957 and then not Unit
.File_Names
(Spec
).Locally_Removed
958 and then Check_Project
(Unit
.File_Names
(Spec
).Project
)
960 Add_ALI_For
(Unit
.File_Names
(Spec
).File
);
964 Unit
:= Units_Htable
.Get_Next
(In_Tree
.Units_HT
);
968 -- Continue setup and call gnatbind if Bind is True
972 -- Get an eventual --RTS from the ALI file
974 if First_ALI
/= No_File
then
982 T
:= Read_Library_Info
(First_ALI
, True);
987 (First_ALI
, T
, Ignore_ED
=> False, Err
=> False);
989 if A
/= No_ALI_Id
then
992 (ALI
.ALIs
.Table
(A
).First_Unit
).First_Arg
..
994 (ALI
.ALIs
.Table
(A
).First_Unit
).Last_Arg
996 -- If --RTS found, add switch to call gnatbind
999 Arg
: String_Ptr
renames Args
.Table
(Index
);
1001 if Arg
'Length >= 6 and then
1002 Arg
(Arg
'First + 2 .. Arg
'First + 5) = "RTS="
1004 Add_Argument
(Arg
.all);
1015 -- First the source path
1017 if For_Project
.Include_Path_File
= No_Path
then
1019 (Project_Tree
=> In_Tree
,
1020 For_Project
=> For_Project
,
1021 Activity
=> Compilation
,
1022 Languages
=> Ada_Only
);
1024 Create_New_Path_File
1025 (In_Tree
.Shared
, Path_FD
, For_Project
.Include_Path_File
);
1027 Write_Path_File
(Path_FD
);
1028 Path_FD
:= Invalid_FD
;
1031 if Current_Source_Path_File_Of
(In_Tree
.Shared
) /=
1032 For_Project
.Include_Path_File
1034 Set_Current_Source_Path_File_Of
1035 (In_Tree
.Shared
, For_Project
.Include_Path_File
);
1037 (Project_Include_Path_File
,
1038 Get_Name_String
(For_Project
.Include_Path_File
));
1041 -- Then, the object path
1044 (Project_Tree
=> In_Tree
,
1045 For_Project
=> For_Project
,
1046 Activity
=> SAL_Binding
,
1047 Languages
=> Ada_Only
);
1050 Path_File_Name
: Path_Name_Type
;
1053 Create_New_Path_File
(In_Tree
.Shared
, Path_FD
, Path_File_Name
);
1055 Write_Path_File
(Path_FD
);
1056 Path_FD
:= Invalid_FD
;
1059 (Project_Objects_Path_File
, Get_Name_String
(Path_File_Name
));
1060 Set_Current_Source_Path_File_Of
1061 (In_Tree
.Shared
, Path_File_Name
);
1064 -- Display the gnatbind command, if not in quiet output
1069 for J
in 1 .. Argument_Number
loop
1070 Size
:= Size
+ Arguments
(J
)'Length + 1;
1073 -- Invoke gnatbind with the arguments if the size is not too large
1075 if Size
<= Maximum_Size
then
1078 Arguments
(1 .. Argument_Number
),
1081 -- Otherwise create a temporary response file
1085 FD
: File_Descriptor
;
1086 Path
: Path_Name_Type
;
1087 Args
: Argument_List
(1 .. 1);
1088 EOL
: constant String (1 .. 1) := (1 => ASCII
.LF
);
1091 Quotes_Needed
: Boolean;
1092 Last_Char
: Natural;
1096 Tempdir
.Create_Temp_File
(FD
, Path
);
1097 Args
(1) := new String'("@" & Get_Name_String (Path));
1099 for J in 1 .. Argument_Number loop
1101 -- Check if the argument should be quoted
1103 Quotes_Needed := False;
1104 Last_Char := Arguments (J)'Length;
1106 for K in Arguments (J)'Range loop
1107 Ch := Arguments (J) (K);
1109 if Ch = ' ' or else Ch = ASCII.HT or else Ch = '"' then
1110 Quotes_Needed := True;
1115 if Quotes_Needed then
1117 -- Quote the argument, doubling '"'
1120 Arg : String (1 .. Arguments (J)'Length * 2 + 2);
1126 for K in Arguments (J)'Range loop
1127 Ch := Arguments (J) (K);
1128 Last_Char := Last_Char + 1;
1129 Arg (Last_Char) := Ch;
1132 Last_Char := Last_Char + 1;
1133 Arg (Last_Char) := '"';
1137 Last_Char := Last_Char + 1;
1138 Arg (Last_Char) := '"';
1140 Status := Write (FD, Arg'Address, Last_Char);
1146 Arguments (J) (Arguments (J)'First)'Address,
1150 if Status /= Last_Char then
1154 Status := Write (FD, EOL (1)'Address, 1);
1163 -- And invoke gnatbind with this response file
1165 Spawn (Gnatbind_Path.all, Args, Success);
1167 Delete_File (Get_Name_String (Path), Succ);
1169 -- We ignore a failure in this Delete_File operation.
1170 -- Is that OK??? If so, worth a comment as to why we
1171 -- are OK with the operation failing
1176 Com.Fail ("could not bind standalone library "
1177 & Get_Name_String (For_Project.Library_Name));
1181 -- Compile the binder generated file only if Link is true
1188 (Project => For_Project,
1190 Including_Libraries => True);
1192 -- Invoke <gcc> -c b__<lib>.adb
1194 -- Allocate Arguments, if first time we see a standalone library
1196 if Arguments = No_Argument then
1197 Arguments := new String_List (1 .. Initial_Argument_Max);
1200 Argument_Number := 2;
1201 Arguments (1) := Compile_Switch;
1202 Arguments (2) := No_Warning;
1205 (B_Start & Get_Name_String (For_Project.Library_Name) & ".adb");
1207 -- If necessary, add the PIC option
1209 if PIC_Option /= "" then
1210 Add_Argument (PIC_Option);
1213 -- Get the back-end switches and --RTS from the ALI file
1215 if First_ALI /= No_File then
1217 T : Text_Buffer_Ptr;
1221 -- Load the ALI file
1223 T := Read_Library_Info (First_ALI, True);
1228 Scan_ALI (First_ALI, T, Ignore_ED => False, Err => False);
1230 if A /= No_ALI_Id then
1233 (ALI.ALIs.Table (A).First_Unit).First_Arg ..
1235 (ALI.ALIs.Table (A).First_Unit).Last_Arg
1237 -- Do not compile with the front end switches except
1241 Arg : String_Ptr renames Args.Table (Index);
1243 if not Is_Front_End_Switch (Arg.all)
1245 Arg (Arg'First + 2 .. Arg'First + 5) = "RTS="
1247 Add_Argument (Arg.all);
1255 -- Now all the arguments are set, compile binder generated file
1259 (Gcc_Path.all, Arguments (1 .. Argument_Number), Success);
1263 ("could not compile binder generated file for library "
1264 & Get_Name_String (For_Project.Library_Name));
1267 -- Process binder generated file for pragmas Linker_Options
1269 Process_Binder_File (Arguments (3).all & ASCII.NUL);
1273 -- Build the library only if Link is True
1277 -- If attributes Library_GCC or Linker'Driver were specified, get the
1280 if For_Project.Config.Shared_Lib_Driver /= No_File then
1281 Driver_Name := Name_Id (For_Project.Config.Shared_Lib_Driver);
1284 -- If attribute Library_Options was specified, add these options
1286 Library_Options := Value_Of
1287 (Name_Library_Options, For_Project.Decl.Attributes,
1290 if not Library_Options.Default then
1292 Current : String_List_Id;
1293 Element : String_Element;
1296 Current := Library_Options.Values;
1297 while Current /= Nil_String loop
1298 Element := In_Tree.Shared.String_Elements.Table (Current);
1299 Get_Name_String (Element.Value);
1301 if Name_Len /= 0 then
1302 Opts.Increment_Last;
1303 Opts.Table (Opts.Last) :=
1304 new String'(Name_Buffer
(1 .. Name_Len
));
1307 Current
:= Element
.Next
;
1313 new String'(Get_Name_String (For_Project.Library_Dir.Display_Name));
1315 new String'(Get_Name_String
(For_Project
.Library_Name
));
1317 case For_Project
.Library_Kind
is
1319 The_Build_Mode
:= Static
;
1322 The_Build_Mode
:= Dynamic
;
1325 The_Build_Mode
:= Relocatable
;
1327 if PIC_Option
/= "" then
1328 Opts
.Increment_Last
;
1329 Opts
.Table
(Opts
.Last
) := new String'(PIC_Option);
1333 -- Get the library version, if any
1335 if For_Project.Lib_Internal_Name /= No_Name then
1337 new String'(Get_Name_String
(For_Project
.Lib_Internal_Name
));
1340 -- Add the objects found in the object directory and the object
1341 -- directories of the extended files, if any, except for generated
1342 -- object files (b~.. or B__..) from extended projects.
1343 -- When there are one or more extended files, only add an object file
1344 -- if no object file with the same name have already been added.
1346 In_Main_Object_Directory
:= True;
1348 -- For gnatmake, when the project specifies more than just Ada as a
1349 -- language (even if course we could not find any source file for
1350 -- the other languages), we will take all object files found in the
1351 -- object directories. Since we know the project supports at least
1352 -- Ada, we just have to test whether it has at least two languages,
1353 -- and not care about the sources.
1355 Foreign_Sources
:= For_Project
.Languages
.Next
/= null;
1356 Current_Proj
:= For_Project
;
1358 if Current_Proj
.Object_Directory
/= No_Path_Information
then
1360 -- The following code gets far too indented ... suggest some
1361 -- procedural abstraction here. How about making this declare
1362 -- block a named procedure???
1365 Object_Dir_Path
: constant String :=
1367 (Current_Proj
.Object_Directory
1370 Object_Dir
: Dir_Type
;
1371 Filename
: String (1 .. 255);
1376 Open
(Dir
=> Object_Dir
, Dir_Name
=> Object_Dir_Path
);
1378 -- For all entries in the object directory
1381 Read
(Object_Dir
, Filename
, Last
);
1385 -- Check if it is an object file
1387 if Is_Obj
(Filename
(1 .. Last
)) then
1389 Object_Path
: constant String :=
1392 & Directory_Separator
1393 & Filename
(1 .. Last
));
1394 Object_File
: constant String :=
1395 Filename
(1 .. Last
);
1397 C_Filename
: String := Object_File
;
1400 Canonical_Case_File_Name
(C_Filename
);
1402 -- If in the object directory of an extended
1403 -- project, do not consider generated object files.
1405 if In_Main_Object_Directory
1408 C_Filename
(1 .. B_Start
'Length) /= B_Start
1411 Add_Str_To_Name_Buffer
(C_Filename
);
1414 if not Objects_Htable
.Get
(Id
) then
1416 ALI_File
: constant String :=
1417 Ext_To
(C_Filename
, "ali");
1419 ALI_Path
: constant String :=
1420 Ext_To
(Object_Path
, "ali");
1423 Fname
: File_Name_Type
;
1428 -- The following assignment could use
1436 C_Filename
(1 .. B_Start
'Length)
1439 if Is_Regular_File
(ALI_Path
) then
1441 -- If there is an ALI file, check if
1442 -- the object file should be added to
1443 -- the library. If there are foreign
1444 -- sources we put all object files in
1449 Units_Htable
.Get_First
1451 while Index
/= null loop
1452 if Index
.File_Names
(Impl
) /=
1456 Index
.File_Names
(Impl
)
1459 Index
.File_Names
(Impl
).File
;
1461 elsif Index
.File_Names
(Spec
) /=
1465 Index
.File_Names
(Spec
)
1468 Index
.File_Names
(Spec
).File
;
1474 Add_It
:= Proj
/= No_Project
;
1476 -- If the source is in the
1477 -- project or a project it
1478 -- extends, we may put it in
1482 Add_It
:= Check_Project
(Proj
);
1485 -- But we don't, if the ALI file
1486 -- does not correspond to the
1491 F
: constant String :=
1496 Add_It
:= F
= ALI_File
;
1503 Units_Htable
.Get_Next
1509 Objects_Htable
.Set
(Id
, True);
1511 (new String'(Object_Path));
1513 -- Record the ALI file
1515 ALIs.Append (new String'(ALI_Path
));
1517 -- Find out if for this ALI file,
1518 -- libgnarl is necessary.
1520 Check_Libs
(ALI_Path
, True);
1523 elsif Foreign_Sources
then
1525 (new String'(Object_Path));
1534 Close (Dir => Object_Dir);
1537 when Directory_Error =>
1538 Com.Fail ("cannot find object directory """
1540 (Current_Proj.Object_Directory.Display_Name)
1545 exit when Current_Proj.Extends = No_Project;
1547 In_Main_Object_Directory := False;
1548 Current_Proj := Current_Proj.Extends;
1551 -- Add the -L and -l switches for the imported Library Project Files,
1552 -- and, if Path Option is supported, the library directory path names
1555 Process_Imported_Libraries;
1557 -- Link with libgnat and possibly libgnarl
1559 Opts.Increment_Last;
1560 Opts.Table (Opts.Last) := new String'("-L" & Lib_Directory
);
1562 -- If Path Option supported, add libgnat directory path name to Rpath
1564 if Path_Option
/= null then
1566 Libdir
: constant String := Lib_Directory
;
1567 GCC_Index
: Natural := 0;
1572 -- For shared libraries, add to the Path Option the directory
1573 -- of the shared version of libgcc.
1575 if The_Build_Mode
/= Static
then
1576 GCC_Index
:= Index
(Libdir
, "/lib/");
1578 if GCC_Index
= 0 then
1582 Directory_Separator
& "lib" & Directory_Separator
);
1585 if GCC_Index
/= 0 then
1586 Add_Rpath
(Libdir
(Libdir
'First .. GCC_Index
+ 3));
1592 if Libgnarl_Needed
= Yes
then
1593 Opts
.Increment_Last
;
1595 if The_Build_Mode
= Static
then
1596 Opts
.Table
(Opts
.Last
) := new String'("-lgnarl");
1598 Opts.Table (Opts.Last) := new String'(Shared_Lib
("gnarl"));
1602 Opts
.Increment_Last
;
1604 if The_Build_Mode
= Static
then
1605 Opts
.Table
(Opts
.Last
) := new String'("-lgnat");
1607 Opts.Table (Opts.Last) := new String'(Shared_Lib
("gnat"));
1610 -- If Path Option is supported, add the necessary switch with the
1611 -- content of Rpath. As Rpath contains at least libgnat directory
1612 -- path name, it is guaranteed that it is not null.
1614 if Opt
.Run_Path_Option
and then Path_Option
/= null then
1615 Opts
.Increment_Last
;
1616 Opts
.Table
(Opts
.Last
) :=
1617 new String'(Path_Option.all & Rpath (1 .. Rpath_Last));
1624 (Argument_List
(Objects
.Table
(1 .. Objects
.Last
)));
1627 new Argument_List
'(Argument_List (ALIs.Table (1 .. ALIs.Last)));
1630 new Argument_List'(Argument_List
(Opts
.Table
(1 .. Opts
.Last
)));
1632 -- We fail if there are no object to put in the library
1633 -- (Ada or foreign objects).
1635 if Object_Files
'Length = 0 then
1636 Com
.Fail
("no object files for library """ &
1637 Lib_Filename
.all & '"');
1640 if not Opt
.Quiet_Output
then
1642 Write_Str
("building ");
1643 Write_Str
(Ada
.Characters
.Handling
.To_Lower
1644 (Build_Mode_State
'Image (The_Build_Mode
)));
1645 Write_Str
(" library for project ");
1646 Write_Line
(Project_Name
);
1648 -- Only output list of object files and ALI files in verbose mode
1650 if Opt
.Verbose_Mode
then
1653 Write_Line
("object files:");
1655 for Index
in Object_Files
'Range loop
1657 Write_Line
(Object_Files
(Index
).all);
1662 if Ali_Files
'Length = 0 then
1663 Write_Line
("NO ALI files");
1666 Write_Line
("ALI files:");
1668 for Index
in Ali_Files
'Range loop
1670 Write_Line
(Ali_Files
(Index
).all);
1678 -- We check that all object files are regular files
1682 -- Delete the existing library file, if it exists. Fail if the
1683 -- library file is not writable, or if it is not possible to delete
1687 DLL_Name
: aliased String :=
1688 Lib_Dirpath
.all & Directory_Separator
& DLL_Prefix
&
1689 Lib_Filename
.all & "." & DLL_Ext
;
1691 Archive_Name
: aliased String :=
1692 Lib_Dirpath
.all & Directory_Separator
& "lib" &
1693 Lib_Filename
.all & "." & Archive_Ext
;
1695 type Str_Ptr
is access all String;
1696 -- This type is necessary to meet the accessibility rules of Ada.
1697 -- It is not possible to use String_Access here.
1699 Full_Lib_Name
: Str_Ptr
;
1700 -- Designates the full library path name. Either DLL_Name or
1701 -- Archive_Name, depending on the library kind.
1704 pragma Warnings
(Off
, Success
);
1705 -- Used to call Delete_File
1708 if The_Build_Mode
= Static
then
1709 Full_Lib_Name
:= Archive_Name
'Access;
1711 Full_Lib_Name
:= DLL_Name
'Access;
1714 if Is_Regular_File
(Full_Lib_Name
.all) then
1715 if Is_Writable_File
(Full_Lib_Name
.all) then
1716 Delete_File
(Full_Lib_Name
.all, Success
);
1719 if Is_Regular_File
(Full_Lib_Name
.all) then
1720 Com
.Fail
("could not delete """ & Full_Lib_Name
.all & """");
1725 Argument_Number
:= 0;
1727 -- If we have a standalone library, gather all the interface ALI.
1728 -- They are flagged as Interface when we copy them to the library
1729 -- directory (by Copy_ALI_Files, below).
1732 Current_Proj
:= For_Project
;
1735 Iface
: String_List_Id
:= For_Project
.Lib_Interface_ALIs
;
1736 ALI
: File_Name_Type
;
1739 while Iface
/= Nil_String
loop
1742 (In_Tree
.Shared
.String_Elements
.Table
(Iface
).Value
);
1743 Interface_ALIs
.Set
(ALI
, True);
1745 (In_Tree
.Shared
.String_Elements
.Table
(Iface
).Value
);
1746 Add_Argument
(Name_Buffer
(1 .. Name_Len
));
1747 Iface
:= In_Tree
.Shared
.String_Elements
.Table
(Iface
).Next
;
1750 Iface
:= For_Project
.Lib_Interface_ALIs
;
1752 if not Opt
.Quiet_Output
then
1754 -- Check that the interface set is complete: any unit in the
1755 -- library that is needed by an interface should also be an
1756 -- interface. If it is not the case, output a warning.
1758 while Iface
/= Nil_String
loop
1761 (In_Tree
.Shared
.String_Elements
.Table
(Iface
).Value
);
1764 In_Tree
.Shared
.String_Elements
.Table
(Iface
).Next
;
1771 Current_Dir
: constant String := Get_Current_Dir
;
1774 Name
: String (1 .. 200);
1777 Disregard
: Boolean;
1778 pragma Warnings
(Off
, Disregard
);
1780 DLL_Name
: aliased constant String :=
1781 Lib_Filename
.all & "." & DLL_Ext
;
1783 Archive_Name
: aliased constant String :=
1784 Lib_Filename
.all & "." & Archive_Ext
;
1786 Delete
: Boolean := False;
1789 -- Clean the library directory: remove any file with the name of
1790 -- the library file and any ALI file of a source of the project.
1793 Get_Name_String
(For_Project
.Library_Dir
.Display_Name
);
1794 Change_Dir
(Name_Buffer
(1 .. Name_Len
));
1799 ("unable to access library directory """
1800 & Name_Buffer
(1 .. Name_Len
)
1807 Read
(Dir
, Name
, Last
);
1811 Filename
: constant String := Name
(1 .. Last
);
1814 if Is_Regular_File
(Filename
) then
1815 Canonical_Case_File_Name
(Name
(1 .. Last
));
1818 if (The_Build_Mode
= Static
1819 and then Name
(1 .. Last
) = Archive_Name
)
1821 ((The_Build_Mode
= Dynamic
1823 The_Build_Mode
= Relocatable
)
1824 and then Name
(1 .. Last
) = DLL_Name
)
1829 and then Name
(Last
- 3 .. Last
) = ".ali"
1835 -- Compare with ALI file names of the project
1837 Unit
:= Units_Htable
.Get_First
(In_Tree
.Units_HT
);
1838 while Unit
/= No_Unit_Index
loop
1839 if Unit
.File_Names
(Impl
) /= null
1840 and then Unit
.File_Names
(Impl
).Project
/=
1843 if Ultimate_Extending_Project_Of
1844 (Unit
.File_Names
(Impl
).Project
) =
1848 (Unit
.File_Names
(Impl
).File
);
1852 (Name
(1 .. Name_Len
))'Length;
1854 if Name_Buffer
(1 .. Name_Len
) =
1855 Name
(1 .. Last
- 4)
1862 elsif Unit
.File_Names
(Spec
) /= null
1863 and then Ultimate_Extending_Project_Of
1864 (Unit
.File_Names
(Spec
).Project
) =
1867 Get_Name_String
(Unit
.File_Names
(Spec
).File
);
1870 File_Extension
(Name
(1 .. Last
))'Length;
1872 if Name_Buffer
(1 .. Name_Len
) =
1873 Name
(1 .. Last
- 4)
1880 Unit
:= Units_Htable
.Get_Next
(In_Tree
.Units_HT
);
1886 Set_Writable
(Filename
);
1887 Delete_File
(Filename
, Disregard
);
1895 Change_Dir
(Current_Dir
);
1898 -- Call procedure to build the library, depending on the build mode
1900 case The_Build_Mode
is
1904 Build_Dynamic_Library
1905 (Ofiles
=> Object_Files
.all,
1906 Options
=> Options
.all,
1907 Interfaces
=> Arguments
(1 .. Argument_Number
),
1908 Lib_Filename
=> Lib_Filename
.all,
1909 Lib_Dir
=> Lib_Dirpath
.all,
1910 Symbol_Data
=> Current_Proj
.Symbol_Data
,
1911 Driver_Name
=> Driver_Name
,
1912 Lib_Version
=> Lib_Version
.all,
1913 Auto_Init
=> Current_Proj
.Lib_Auto_Init
);
1925 -- We need to copy the ALI files from the object directory to the
1926 -- library ALI directory, so that the linker find them there, and
1927 -- does not need to look in the object directory where it would also
1928 -- find the object files; and we don't want that: we want the linker
1929 -- to use the library.
1931 -- Copy the ALI files and make the copies read-only. For interfaces,
1932 -- mark the copies as interfaces.
1935 (Files
=> Ali_Files
.all,
1936 To
=> For_Project
.Library_ALI_Dir
.Display_Name
,
1937 Interfaces
=> Arguments
(1 .. Argument_Number
));
1939 -- Copy interface sources if Library_Src_Dir specified
1942 and then For_Project
.Library_Src_Dir
/= No_Path_Information
1944 -- Clean the interface copy directory: remove any source that
1945 -- could be a source of the project.
1948 Get_Name_String
(For_Project
.Library_Src_Dir
.Display_Name
);
1949 Change_Dir
(Name_Buffer
(1 .. Name_Len
));
1954 ("unable to access library source copy directory """
1955 & Name_Buffer
(1 .. Name_Len
)
1961 Delete
: Boolean := False;
1964 Name
: String (1 .. 200);
1967 Disregard
: Boolean;
1968 pragma Warnings
(Off
, Disregard
);
1974 Read
(Dir
, Name
, Last
);
1977 if Is_Regular_File
(Name
(1 .. Last
)) then
1978 Canonical_Case_File_Name
(Name
(1 .. Last
));
1981 -- Compare with source file names of the project
1983 Unit
:= Units_Htable
.Get_First
(In_Tree
.Units_HT
);
1984 while Unit
/= No_Unit_Index
loop
1985 if Unit
.File_Names
(Impl
) /= null
1986 and then Ultimate_Extending_Project_Of
1987 (Unit
.File_Names
(Impl
).Project
) = For_Project
1990 (Unit
.File_Names
(Impl
).File
) =
1997 if Unit
.File_Names
(Spec
) /= null
1998 and then Ultimate_Extending_Project_Of
1999 (Unit
.File_Names
(Spec
).Project
) =
2003 (Unit
.File_Names
(Spec
).File
) =
2010 Unit
:= Units_Htable
.Get_Next
(In_Tree
.Units_HT
);
2015 Set_Writable
(Name
(1 .. Last
));
2016 Delete_File
(Name
(1 .. Last
), Disregard
);
2023 Copy_Interface_Sources
2024 (For_Project
=> For_Project
,
2026 Interfaces
=> Arguments
(1 .. Argument_Number
),
2027 To_Dir
=> For_Project
.Library_Src_Dir
.Display_Name
);
2031 -- Reset the current working directory to its previous value
2033 Change_Dir
(Current_Dir
);
2040 procedure Check
(Filename
: String) is
2042 if not Is_Regular_File
(Filename
) then
2043 Com
.Fail
(Filename
& " not found.");
2051 procedure Check_Context
is
2053 -- Check that each object file exists
2055 for F
in Object_Files
'Range loop
2056 Check
(Object_Files
(F
).all);
2064 procedure Check_Library
2065 (For_Project
: Project_Id
; In_Tree
: Project_Tree_Ref
)
2067 Lib_TS
: Time_Stamp_Type
;
2068 Current
: constant Dir_Name_Str
:= Get_Current_Dir
;
2071 -- No need to build the library if there is no object directory,
2072 -- hence no object files to build the library.
2074 if For_Project
.Library
then
2076 Lib_Name
: constant File_Name_Type
:=
2077 Library_File_Name_For
(For_Project
, In_Tree
);
2080 (Get_Name_String
(For_Project
.Library_Dir
.Display_Name
));
2081 Lib_TS
:= File_Stamp
(Lib_Name
);
2082 For_Project
.Library_TS
:= Lib_TS
;
2085 if not For_Project
.Externally_Built
2086 and then not For_Project
.Need_To_Build_Lib
2087 and then For_Project
.Object_Directory
/= No_Path_Information
2090 Obj_TS
: Time_Stamp_Type
;
2091 Object_Dir
: Dir_Type
;
2094 -- If the library file does not exist, then the time stamp will
2095 -- be Empty_Time_Stamp, earlier than any other time stamp.
2098 (Get_Name_String
(For_Project
.Object_Directory
.Display_Name
));
2099 Open
(Dir
=> Object_Dir
, Dir_Name
=> ".");
2101 -- For all entries in the object directory
2104 Read
(Object_Dir
, Name_Buffer
, Name_Len
);
2105 exit when Name_Len
= 0;
2107 -- Check if it is an object file, but ignore any binder
2110 if Is_Obj
(Name_Buffer
(1 .. Name_Len
))
2111 and then Name_Buffer
(1 .. B_Start
'Length) /= B_Start
2113 -- Get the object file time stamp
2115 Obj_TS
:= File_Stamp
(File_Name_Type
'(Name_Find));
2117 -- If library file time stamp is earlier, set
2118 -- Need_To_Build_Lib and return. String comparison is
2119 -- used, otherwise time stamps may be too close and the
2120 -- comparison would return True, which would trigger
2121 -- an unnecessary rebuild of the library.
2123 if String (Lib_TS) < String (Obj_TS) then
2125 -- Library must be rebuilt
2127 For_Project.Need_To_Build_Lib := True;
2137 Change_Dir (Current);
2141 ----------------------------
2142 -- Copy_Interface_Sources --
2143 ----------------------------
2145 procedure Copy_Interface_Sources
2146 (For_Project : Project_Id;
2147 In_Tree : Project_Tree_Ref;
2148 Interfaces : Argument_List;
2149 To_Dir : Path_Name_Type)
2151 Current : constant Dir_Name_Str := Get_Current_Dir;
2152 -- The current directory, where to return to at the end
2154 Target : constant Dir_Name_Str := Get_Name_String (To_Dir);
2155 -- The directory where to copy sources
2157 Text : Text_Buffer_Ptr;
2158 The_ALI : ALI.ALI_Id;
2159 Lib_File : File_Name_Type;
2161 First_Unit : ALI.Unit_Id;
2162 Second_Unit : ALI.Unit_Id;
2164 Copy_Subunits : Boolean := False;
2165 -- When True, indicates that subunits, if any, need to be copied too
2167 procedure Copy (File_Name : File_Name_Type);
2168 -- Copy one source of the project to the target directory
2174 procedure Copy (File_Name : File_Name_Type) is
2176 pragma Warnings (Off, Success);
2178 Source : Standard.Prj.Source_Id;
2180 Source := Find_Source
2181 (In_Tree, For_Project,
2182 In_Extended_Only => True,
2183 Base_Name => File_Name);
2185 if Source /= No_Source
2186 and then not Source.Locally_Removed
2187 and then Source.Replaced_By = No_Source
2190 (Get_Name_String (Source.Path.Name),
2194 Preserve => Preserve);
2198 -- Start of processing for Copy_Interface_Sources
2201 -- Change the working directory to the object directory
2203 Change_Dir (Get_Name_String (For_Project.Object_Directory.Display_Name));
2205 for Index in Interfaces'Range loop
2207 -- First, load the ALI file
2210 Add_Str_To_Name_Buffer (Interfaces (Index).all);
2211 Lib_File := Name_Find;
2212 Text := Read_Library_Info (Lib_File);
2213 The_ALI := Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True);
2216 Second_Unit := No_Unit_Id;
2217 First_Unit := ALI.ALIs.Table (The_ALI).First_Unit;
2218 Copy_Subunits := True;
2220 -- If there is both a spec and a body, check if they are both needed
2222 if ALI.Units.Table (First_Unit).Utype = Is_Body then
2223 Second_Unit := ALI.ALIs.Table (The_ALI).Last_Unit;
2225 -- If the body is not needed, then reset First_Unit
2227 if not ALI.Units.Table (Second_Unit).Body_Needed_For_SAL then
2228 First_Unit := No_Unit_Id;
2229 Copy_Subunits := False;
2232 elsif ALI.Units.Table (First_Unit).Utype = Is_Spec_Only then
2233 Copy_Subunits := False;
2236 -- Copy the file(s) that need to be copied
2238 if First_Unit /= No_Unit_Id then
2239 Copy (File_Name => ALI.Units.Table (First_Unit).Sfile);
2242 if Second_Unit /= No_Unit_Id then
2243 Copy (File_Name => ALI.Units.Table (Second_Unit).Sfile);
2246 -- Copy all the separates, if any
2248 if Copy_Subunits then
2249 for Dep in ALI.ALIs.Table (The_ALI).First_Sdep ..
2250 ALI.ALIs.Table (The_ALI).Last_Sdep
2252 if Sdep.Table (Dep).Subunit_Name /= No_Name then
2253 Copy (File_Name => Sdep.Table (Dep).Sfile);
2259 -- Restore the initial working directory
2261 Change_Dir (Current);
2262 end Copy_Interface_Sources;
2268 procedure Display (Executable : String) is
2270 if not Opt.Quiet_Output then
2271 Write_Str (Executable);
2273 for Index in 1 .. Argument_Number loop
2275 Write_Str (Arguments (Index).all);
2277 if not Opt.Verbose_Mode and then Index > 4 then
2291 function Index (S, Pattern : String) return Natural is
2292 Len : constant Natural := Pattern'Length;
2295 for J in reverse S'First .. S'Last - Len + 1 loop
2296 if Pattern = S (J .. J + Len - 1) then
2304 -------------------------
2305 -- Process_Binder_File --
2306 -------------------------
2308 procedure Process_Binder_File (Name : String) is
2310 -- Binder file's descriptor
2312 Read_Mode : constant String := "r" & ASCII.NUL;
2315 Status : Interfaces.C_Streams.int;
2316 pragma Unreferenced (Status);
2319 Begin_Info : constant String := "-- BEGIN Object file/option list";
2320 End_Info : constant String := "-- END Object file/option list ";
2322 Next_Line : String (1 .. 1000);
2323 -- Current line value
2324 -- Where does this odd constant 1000 come from, looks suspicious ???
2327 -- End of line slice (the slice does not contain the line terminator)
2329 procedure Get_Next_Line;
2330 -- Read the next line from the binder file without the line terminator
2336 procedure Get_Next_Line is
2340 Fchars := fgets (Next_Line'Address, Next_Line'Length, Fd);
2342 if Fchars = System.Null_Address then
2343 Fail ("Error reading binder output");
2347 while Nlast <= Next_Line'Last
2348 and then Next_Line (Nlast) /= ASCII.LF
2349 and then Next_Line (Nlast) /= ASCII.CR
2357 -- Start of processing for Process_Binder_File
2360 Fd := fopen (Name'Address, Read_Mode'Address);
2362 if Fd = NULL_Stream then
2363 Fail ("Failed to open binder output");
2366 -- Skip up to the Begin Info line
2370 exit when Next_Line (1 .. Nlast) = Begin_Info;
2373 -- Find the first switch
2378 exit when Next_Line (1 .. Nlast) = End_Info;
2380 -- As the binder generated file is in Ada, remove the first eight
2381 -- characters " -- ".
2383 Next_Line (1 .. Nlast - 8) := Next_Line (9 .. Nlast);
2386 -- Stop when the first switch is found
2388 exit when Next_Line (1) = '-';
2391 if Next_Line (1 .. Nlast) /= End_Info then
2393 -- Ignore -static and -shared, since -shared will be used
2396 -- Ignore -lgnat and -lgnarl as they will be added later,
2397 -- because they are also needed for non Stand-Alone shared
2400 -- Also ignore the shared libraries which are:
2402 -- -lgnat-<version> (7 + version'length chars)
2403 -- -lgnarl-<version> (8 + version'length chars)
2405 if Next_Line (1 .. Nlast) /= "-static" and then
2406 Next_Line (1 .. Nlast) /= "-shared" and then
2407 Next_Line (1 .. Nlast) /= "-lgnarl" and then
2408 Next_Line (1 .. Nlast) /= "-lgnat"
2411 (1 .. Natural'Min (Nlast, 8 + Library_Version'Length)) /=
2412 Shared_Lib ("gnarl")
2415 (1 .. Natural'Min (Nlast, 7 + Library_Version'Length)) /=
2418 if Next_Line (1) /= '-' then
2420 -- This is not an option, should we add it?
2422 if Add_Object_Files then
2423 Opts.Increment_Last;
2424 Opts.Table (Opts.Last) :=
2425 new String'(Next_Line
(1 .. Nlast
));
2429 -- Add all other options
2431 Opts
.Increment_Last
;
2432 Opts
.Table
(Opts
.Last
) :=
2433 new String'(Next_Line (1 .. Nlast));
2437 -- Next option, if any
2440 exit when Next_Line (1 .. Nlast) = End_Info;
2442 -- Remove first eight characters " -- "
2444 Next_Line (1 .. Nlast - 8) := Next_Line (9 .. Nlast);
2449 Status := fclose (Fd);
2451 -- Is it really right to ignore any close error ???
2453 end Process_Binder_File;
2459 procedure Reset_Tables is
2462 Objects_Htable.Reset;
2465 Processed_Projects.Reset;
2469 ---------------------------
2470 -- SALs_Use_Constructors --
2471 ---------------------------
2473 function SALs_Use_Constructors return Boolean is
2474 function C_SALs_Init_Using_Constructors return Integer;
2475 pragma Import (C, C_SALs_Init_Using_Constructors,
2476 "__gnat_sals_init_using_constructors");
2478 return C_SALs_Init_Using_Constructors /= 0;
2479 end SALs_Use_Constructors;