nitc: fix duplication on imports of public foreign code
[nit.git] / src / ffi / header_dependency.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Tracks which modules has public header code that must be imported
18 # by user modules.
19 module header_dependency
20
21 import ffi_base
22 import c
23
24 redef class ToolContext
25 var header_dependancy_phase: Phase = new HeaderDependancyPhase(self, [ffi_language_assignation_phase, modelize_class_phase])
26 end
27
28 redef class AModule
29 private fun has_public_c_header: Bool do
30 for code_block in n_extern_code_blocks do if code_block.is_c_header then return true
31 return false
32 end
33 end
34
35 redef class MModule
36 # Modules with public foreign code blocks (C header)
37 var header_dependencies: nullable HashSet[MModule] = null
38
39 private fun compute_header_dependencies(v: HeaderDependancyPhase)
40 do
41 if header_dependencies != null then return
42
43 var header_dependencies = new HashSet[MModule]
44
45 # gather from importation
46 for m in in_importation.direct_greaters do
47 m.compute_header_dependencies v
48
49 # does the super module has inherited dependencies?
50 var hd = m.header_dependencies
51 assert hd != null
52 if not hd.is_empty then
53 header_dependencies.add_all hd
54 end
55
56 # does the super module itself has extern dependencies?
57 var amodule = v.toolcontext.modelbuilder.mmodule2node(m)
58 if amodule != null and amodule.has_public_c_header then header_dependencies.add(m)
59 end
60
61 self.header_dependencies = header_dependencies
62 end
63 end
64
65 private class HeaderDependancyPhase
66 super Phase
67
68 redef fun process_nmodule(nmodule)
69 do
70 var mmodule = nmodule.mmodule
71 mmodule.compute_header_dependencies(self)
72 end
73 end