1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
|
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- M L I B . P R J --
-- --
-- B o d y --
-- --
-- --
-- Copyright (C) 2001, Ada Core Technologies, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 2, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
-- Public License distributed with GNAT; see file COPYING. If not, write --
-- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
-- MA 02111-1307, USA. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
-- --
------------------------------------------------------------------------------
with Ada.Characters.Handling;
with GNAT.Directory_Operations; use GNAT.Directory_Operations;
with GNAT.OS_Lib; use GNAT.OS_Lib;
with MLib.Fil;
with MLib.Tgt;
with Opt;
with Output; use Output;
with Osint; use Osint;
with Namet; use Namet;
with Table;
with Types; use Types;
package body MLib.Prj is
package Files renames MLib.Fil;
package Target renames MLib.Tgt;
-- List of objects to put inside the library
Object_Files : Argument_List_Access;
package Objects is new Table.Table
(Table_Name => "Mlib.Prj.Objects",
Table_Component_Type => String_Access,
Table_Index_Type => Natural,
Table_Low_Bound => 1,
Table_Initial => 50,
Table_Increment => 50);
-- List of non-Ada object files
Foreign_Objects : Argument_List_Access;
package Foreigns is new Table.Table
(Table_Name => "Mlib.Prj.Foreigns",
Table_Component_Type => String_Access,
Table_Index_Type => Natural,
Table_Low_Bound => 1,
Table_Initial => 20,
Table_Increment => 20);
-- List of ALI files
Ali_Files : Argument_List_Access;
package Alis is new Table.Table
(Table_Name => "Mlib.Prj.Alis",
Table_Component_Type => String_Access,
Table_Index_Type => Natural,
Table_Low_Bound => 1,
Table_Initial => 50,
Table_Increment => 50);
-- List of options set in the command line.
Options : Argument_List_Access;
package Opts is new Table.Table
(Table_Name => "Mlib.Prj.Opts",
Table_Component_Type => String_Access,
Table_Index_Type => Natural,
Table_Low_Bound => 1,
Table_Initial => 5,
Table_Increment => 5);
type Build_Mode_State is
(None, Static, Dynamic, Relocatable);
procedure Check (Filename : String);
-- Check if filename is a regular file. Fail if it is not.
procedure Check_Context;
-- Check each object files in table Object_Files
-- Fail if any of them is not a regular file
procedure Reset_Tables;
-- Make sure that all the above tables are empty
-- (Objects, Foreign_Objects, Ali_Files, Options)
-------------------
-- Build_Library --
-------------------
procedure Build_Library (For_Project : Project_Id) is
Data : constant Project_Data := Projects.Table (For_Project);
Project_Name : constant String :=
Get_Name_String (Data.Name);
Lib_Filename : String_Access;
Lib_Dirpath : String_Access := new String'(".");
DLL_Address : String_Access := new String'(Target.Default_DLL_Address);
Lib_Version : String_Access := new String'("");
The_Build_Mode : Build_Mode_State := None;
begin
Reset_Tables;
-- Fail if project is not a library project
if not Data.Library then
Fail ("project """, Project_Name, """ has no library");
end if;
Lib_Dirpath := new String'(Get_Name_String (Data.Library_Dir));
Lib_Filename := new String'(Get_Name_String (Data.Library_Name));
case Data.Library_Kind is
when Static =>
The_Build_Mode := Static;
when Dynamic =>
The_Build_Mode := Dynamic;
when Relocatable =>
The_Build_Mode := Relocatable;
if Target.PIC_Option /= "" then
Opts.Increment_Last;
Opts.Table (Opts.Last) := new String'(Target.PIC_Option);
end if;
end case;
-- Get the library version, if any
if Data.Lib_Internal_Name /= No_Name then
Lib_Version := new String'(Get_Name_String (Data.Lib_Internal_Name));
end if;
-- Add the objects found in the object directory
declare
Object_Dir : Dir_Type;
Filename : String (1 .. 255);
Last : Natural;
Object_Dir_Path : constant String :=
Get_Name_String (Data.Object_Directory);
begin
Open (Dir => Object_Dir, Dir_Name => Object_Dir_Path);
-- For all entries in the object directory
loop
Read (Object_Dir, Filename, Last);
exit when Last = 0;
-- Check if it is an object file
if Files.Is_Obj (Filename (1 .. Last)) then
-- record this object file
Objects.Increment_Last;
Objects.Table (Objects.Last) :=
new String' (Object_Dir_Path & Directory_Separator &
Filename (1 .. Last));
if Is_Regular_File
(Object_Dir_Path &
Files.Ext_To (Object_Dir_Path &
Filename (1 .. Last), "ali"))
then
-- Record the corresponding ali file
Alis.Increment_Last;
Alis.Table (Alis.Last) :=
new String' (Object_Dir_Path &
Files.Ext_To
(Filename (1 .. Last), "ali"));
else
-- The object file is a foreign object file
Foreigns.Increment_Last;
Foreigns.Table (Foreigns.Last) :=
new String'(Object_Dir_Path &
Filename (1 .. Last));
end if;
end if;
end loop;
Close (Dir => Object_Dir);
exception
when Directory_Error =>
Fail ("cannot find object directory """,
Get_Name_String (Data.Object_Directory),
"""");
end;
-- We want to link some Ada files, so we need to link with
-- the GNAT runtime (libgnat & libgnarl)
if The_Build_Mode = Dynamic or else The_Build_Mode = Relocatable then
Opts.Increment_Last;
Opts.Table (Opts.Last) := new String' ("-lgnarl");
Opts.Increment_Last;
Opts.Table (Opts.Last) := new String' ("-lgnat");
end if;
Object_Files :=
new Argument_List'(Argument_List (Objects.Table (1 .. Objects.Last)));
Foreign_Objects :=
new Argument_List'(Argument_List
(Foreigns.Table (1 .. Foreigns.Last)));
Ali_Files :=
new Argument_List'(Argument_List (Alis.Table (1 .. Alis.Last)));
Options :=
new Argument_List'(Argument_List (Opts.Table (1 .. Opts.Last)));
-- We fail if there are no object to put in the library
-- (Ada or foreign objects)
if Object_Files'Length = 0 then
Fail ("no object files");
end if;
if not Opt.Quiet_Output then
Write_Eol;
Write_Str ("building ");
Write_Str (Ada.Characters.Handling.To_Lower
(Build_Mode_State'Image (The_Build_Mode)));
Write_Str (" library for project ");
Write_Line (Project_Name);
Write_Eol;
end if;
-- We check that all object files are regular files
Check_Context;
-- And we call the procedure to build the library,
-- depending on the build mode
case The_Build_Mode is
when Dynamic | Relocatable =>
Target.Build_Dynamic_Library
(Ofiles => Object_Files.all,
Foreign => Foreign_Objects.all,
Afiles => Ali_Files.all,
Options => Options.all,
Lib_Filename => Lib_Filename.all,
Lib_Dir => Lib_Dirpath.all,
Lib_Address => DLL_Address.all,
Lib_Version => Lib_Version.all,
Relocatable => The_Build_Mode = Relocatable);
when Static =>
MLib.Build_Library
(Object_Files.all,
Ali_Files.all,
Lib_Filename.all,
Lib_Dirpath.all);
when None =>
null;
end case;
-- We need to copy the ALI files from the object directory
-- to the library directory, so that the linker find them
-- there, and does not need to look in the object directory
-- where it would also find the object files; and we don't want
-- that: we want the linker to use the library.
Target.Copy_ALI_Files
(From => Projects.Table (For_Project).Object_Directory,
To => Projects.Table (For_Project).Library_Dir);
end Build_Library;
-----------
-- Check --
-----------
procedure Check (Filename : String) is
begin
if not Is_Regular_File (Filename) then
Fail (Filename, " not found.");
end if;
end Check;
-------------------
-- Check_Context --
-------------------
procedure Check_Context is
begin
-- check that each object file exist
for F in Object_Files'Range loop
Check (Object_Files (F).all);
end loop;
end Check_Context;
------------------
-- Reset_Tables --
------------------
procedure Reset_Tables is
begin
Objects.Init;
Foreigns.Init;
Alis.Init;
Opts.Init;
end Reset_Tables;
end MLib.Prj;
|