1 (***********************************************************************)
5 (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
7 (* Copyright 2002 Institut National de Recherche en Informatique et *)
8 (* en Automatique. All rights reserved. This file is distributed *)
9 (* under the terms of the Q Public License version 1.0. *)
11 (***********************************************************************)
15 (* "Package" a set of .cmx/.o files into one .cmx/.o file having the
16 original compilation units as sub-modules. *)
25 Illegal_renaming
of string * string
26 | Forward_reference
of string * string
27 | Wrong_for_pack
of string * string
29 | Assembler_error
of string
30 | File_not_found
of string
33 exception Error
of error
35 (* Read the unit information from a .cmx file. *)
37 type pack_member_kind
= PM_intf
| PM_impl
of unit_infos
42 pm_kind
: pack_member_kind
}
44 let read_member_info pack_path file
=
46 String.capitalize
(Filename.basename
(chop_extensions file
)) in
48 if Filename.check_suffix file
".cmx" then begin
49 let (info
, crc
) = Compilenv.read_unit_info file
in
50 if info
.ui_name
<> name
51 then raise
(Error
(Illegal_renaming
(file
, info
.ui_name
)));
53 (Compilenv.current_unit_infos
()).ui_symbol ^
"__" ^ info
.ui_name
54 then raise
(Error
(Wrong_for_pack
(file
, pack_path
)));
55 Asmlink.check_consistency file info crc
;
56 Compilenv.cache_unit_info info
;
60 { pm_file
= file
; pm_name
= name; pm_kind
= kind }
62 (* Check absence of forward references *)
64 let check_units members
=
65 let rec check forbidden
= function
68 begin match mb
.pm_kind
with
73 if List.mem
unit forbidden
74 then raise
(Error
(Forward_reference
(mb
.pm_file
, unit))))
77 check (list_remove mb
.pm_name forbidden
) tl
in
78 check (List.map
(fun mb
-> mb
.pm_name
) members
) members
80 (* Make the .o file for the package *)
82 let make_package_object ppf members targetobj targetname coercion
=
83 (* Put the full name of the module in the temporary file name
84 to avoid collisions with MSVC's link /lib in case of successive packs *)
86 Filename.temp_file
(Compilenv.make_symbol
(Some
"")) Config.ext_obj
in
92 | PM_impl _
-> Some
(Ident.create_persistent m
.pm_name
))
94 Asmgen.compile_implementation
95 (chop_extension_if_any
objtemp) ppf
96 (Translmod.transl_store_package
97 components (Ident.create_persistent targetname
) coercion
);
100 (fun m
-> chop_extension_if_any m
.pm_file ^
Config.ext_obj
)
101 (List.filter
(fun m
-> m
.pm_kind
<> PM_intf
) members
) in
104 Config.native_pack_linker
105 (Filename.quote targetobj
)
106 (Filename.quote
objtemp)
107 (Ccomp.quote_files
objfiles) in
108 let retcode = Ccomp.command
ld_cmd in
110 if retcode <> 0 then raise
(Error Linking_error
)
112 (* Make the .cmx file for the package *)
114 let build_package_cmx members cmxfile
=
116 List.map
(fun m
-> m
.pm_name
) members
in
118 List.filter (fun (name, crc
) -> not
(List.mem
name unit_names)) lst
in
122 (fun accu n
-> if List.mem n accu
then accu
else n
:: accu
))
127 match m
.pm_kind
with PM_intf
-> accu
| PM_impl info
-> info
:: accu
)
129 let ui = Compilenv.current_unit_infos
() in
131 { ui_name
= ui.ui_name
;
132 ui_symbol
= ui.ui_symbol
;
134 List.flatten
(List.map
(fun info
-> info
.ui_defines
) units) @
137 (ui.ui_name
, Env.crc_of_unit
ui.ui_name
) ::
138 filter(Asmlink.extract_crc_interfaces
());
140 filter(Asmlink.extract_crc_implementations
());
141 ui_approx
= ui.ui_approx
;
143 union(List.map
(fun info
-> info
.ui_curry_fun
) units);
145 union(List.map
(fun info
-> info
.ui_apply_fun
) units);
147 union(List.map
(fun info
-> info
.ui_send_fun
) units);
149 List.exists
(fun info
-> info
.ui_force_link
) units
151 Compilenv.write_unit_info
pkg_infos cmxfile
153 (* Make the .cmx and the .o for the package *)
155 let package_object_files ppf files targetcmx
156 targetobj targetname coercion
=
158 match !Clflags.for_package
with
160 | Some p
-> p ^
"." ^ targetname
in
161 let members = map_left_right
(read_member_info pack_path) files
in
163 make_package_object ppf
members targetobj targetname coercion
;
164 build_package_cmx members targetcmx
166 (* The entry point *)
168 let package_files ppf files targetcmx
=
172 try find_in_path
!Config.load_path f
173 with Not_found
-> raise
(Error
(File_not_found f
)))
175 let prefix = chop_extensions targetcmx
in
176 let targetcmi = prefix ^
".cmi" in
177 let targetobj = chop_extension_if_any targetcmx ^
Config.ext_obj
in
178 let targetname = String.capitalize
(Filename.basename
prefix) in
179 (* Set the name of the current "input" *)
180 Location.input_name
:= targetcmx
;
181 (* Set the name of the current compunit *)
182 Compilenv.reset ?packname
:!Clflags.for_package
targetname;
184 let coercion = Typemod.package_units
files targetcmi targetname in
185 package_object_files ppf
files targetcmx
targetobj targetname coercion
187 remove_file targetcmx
; remove_file
targetobj;
194 let report_error ppf
= function
195 Illegal_renaming
(file
, id
) ->
196 fprintf ppf
"Wrong file naming: %s@ contains the code for@ %s"
198 | Forward_reference
(file
, ident
) ->
199 fprintf ppf
"Forward reference to %s in file %s" ident file
200 | Wrong_for_pack
(file
, path
) ->
201 fprintf ppf
"File %s@ was not compiled with the `-for-pack %s' option"
203 | File_not_found file
->
204 fprintf ppf
"File %s not found" file
205 | Assembler_error file
->
206 fprintf ppf
"Error while assembling %s" file
208 fprintf ppf
"Error during partial linking"