@@ -217,7 +217,23 @@ let make_bundles files =
217217(* A more refined version of direct_dependencies (found above), which
218218 distinguishes between internal and public dependencies. Keeps less dependency
219219 information, too, since it does not need to generate precise error messages.
220- To be used after Inlining has run. *)
220+ To be used after Inlining has run.
221+
222+ We do not run this on the C grammar (which would presumably be simpler,
223+ because by then we would have built both flavors of headers + C files),
224+ because it does not distinguish between lids and ids, and also because the
225+ grammar is convoluted and makes it hard to access the "name" of a
226+ declaration.
227+
228+ So instead, we anticipate and rely on the fact that:
229+ - to compute the dependencies of the public header, one needs to visit public
230+ (not internal, not private) functions and type declarations, and
231+ - skip the body of functions unless they are "static header", and
232+ - skip the body of type declarations marked as C abstract structs
233+ - to compute the dependencies of the internal header, same deal
234+ - to compute the dependencies of the C header, same deal except all bodies
235+ are visited
236+ *)
221237
222238module StringSet = Set. Make (String )
223239module LidSet = Idents. LidSet
@@ -227,11 +243,30 @@ type deps = {
227243 public : StringSet .t ;
228244}
229245
246+ type all_deps = {
247+ h : deps ;
248+ internal_h : deps ;
249+ c : deps ;
250+ }
251+
230252let empty_deps = { internal = StringSet. empty; public = StringSet. empty }
231253
232254let drop_dinstinction { internal; public } =
233255 List. of_seq (StringSet. to_seq (StringSet. union internal public))
234256
257+ class record_everything gen_dep = object
258+ inherit [_] reduce
259+ method plus { internal = i1 ; public = p1 } { internal = i2 ; public = p2 } =
260+ { internal = StringSet. union i1 i2; public = StringSet. union p1 p2 }
261+ method zero = empty_deps
262+ method! visit_EQualified _ lid =
263+ gen_dep lid
264+ method! visit_TQualified _ lid =
265+ gen_dep lid
266+ method! visit_TApp () lid _ =
267+ gen_dep lid
268+ end
269+
235270let direct_dependencies_with_internal files file_of =
236271 (* Set of decls marked as internal *)
237272 let internal = List. fold_left (fun set (_ , decls ) ->
@@ -247,29 +282,61 @@ let direct_dependencies_with_internal files file_of =
247282 let gen_dep (callee : lident ) =
248283 match file_of callee with
249284 | Some f when f <> fst file && not (Helpers. is_primitive callee) ->
250- (* KPrint.bprintf "In file %s, reference to %a (in file %s)\n" *)
251- (* (fst file) PrintAst.plid callee f; *)
252- if LidSet. mem callee internal then
285+ let is_internal = LidSet. mem callee internal in
286+ KPrint. bprintf " In file %s, reference to %a (in %sheader %s)\n "
287+ (fst file) PrintAst. plid callee (if is_internal then " internal " else " " ) f;
288+ if is_internal then
253289 { empty_deps with internal = StringSet. singleton f }
254290 else
255291 { empty_deps with public = StringSet. singleton f }
256292 | _ ->
257293 empty_deps
258294 in
259- let deps =
260- (object
261- inherit [_] reduce
262- method plus { internal = i1 ; public = p1 } { internal = i2 ; public = p2 } =
263- { internal = StringSet. union i1 i2; public = StringSet. union p1 p2 }
264- method zero = empty_deps
265- method! visit_EQualified _ lid =
266- gen_dep lid
267- method! visit_TQualified _ lid =
268- gen_dep lid
269- method! visit_TApp _ lid _ =
270- gen_dep lid
271- end )#visit_file () file
272- in
295+ let is_inline_static lid = List. exists (fun p -> Bundle. pattern_matches_lid p lid) ! Options. static_header in
296+ let header_deps which = object
297+ inherit (record_everything gen_dep) as super
298+
299+ method! visit_DFunction env cc flags n_cgs n ret name binders body =
300+ let concerns_us =
301+ match which with
302+ | `Public -> not (List. mem Common. Internal flags) && not (List. mem Common. Private flags)
303+ | `Internal -> List. mem Common. Internal flags
304+ in
305+ if concerns_us then
306+ if is_inline_static name then
307+ super#visit_DFunction env cc flags n_cgs n ret name binders body
308+ else
309+ (* ill-typed, but convenient *)
310+ super#visit_DFunction env cc flags n_cgs n ret name binders Helpers. eunit
311+ else
312+ super#zero
313+
314+ method! visit_DType env name flags n_cgs n def =
315+ let concerns_us =
316+ match which with
317+ | `Public -> not (List. mem Common. Internal flags) && not (List. mem Common. Private flags)
318+ | `Internal -> List. mem Common. Internal flags
319+ in
320+ let is_c_abstract_struct = List. mem Common. AbstractStruct flags in
321+ if concerns_us then
322+ if is_c_abstract_struct then
323+ super#visit_DType env name flags n_cgs n (Abbrev TUnit )
324+ else
325+ super#visit_DType env name flags n_cgs n def
326+ else
327+ super#zero
328+ end in
329+ let deps = {
330+ h = (KPrint. bprintf " PUBLIC %s\n " (fst file); header_deps `Public )#visit_file () file;
331+ internal_h = (KPrint. bprintf " INTERNAL %s\n " (fst file); header_deps `Internal )#visit_file () file;
332+ c = (KPrint. bprintf " C %s\n " (fst file); new record_everything gen_dep)#visit_file () file;
333+ } in
334+
335+ if not (StringSet. is_empty deps.h.internal) then
336+ Warn. fatal_error " Unexpected: %s depends on some internal headers: %s\n "
337+ (fst file)
338+ (String. concat " , " (List. of_seq (StringSet. to_seq deps.h.internal)));
339+
273340 StringMap. add (fst file) deps by_file
274341 ) StringMap. empty files
275342
0 commit comments