]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Java/Source/GenBuild/org/tianocore/build/autogen/AutogenLibOrder.java
Fixed the issue in multi-msa build in single mode; cleaned the code of re-ordering...
[mirror_edk2.git] / Tools / Java / Source / GenBuild / org / tianocore / build / autogen / AutogenLibOrder.java
CommitLineData
878ddf1f 1/**@file\r
2 AutogenLibOrder class.\r
3\r
4 This class is to reorder library instance sequence according to library \r
5 dependence.\r
6 \r
7 Copyright (c) 2006, Intel Corporation\r
8 All rights reserved. This program and the accompanying materials\r
9 are licensed and made available under the terms and conditions of the BSD License\r
10 which accompanies this distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
12 \r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16 **/\r
17package org.tianocore.build.autogen;\r
18\r
19import java.util.ArrayList;\r
20import java.util.HashMap;\r
3dc87a3e 21import java.util.Iterator;\r
22import java.util.LinkedList;\r
878ddf1f 23import java.util.List;\r
24import java.util.Map;\r
3dc87a3e 25import java.util.Stack;\r
26import java.util.HashSet;\r
a29c47e0 27\r
878ddf1f 28import org.apache.xmlbeans.XmlObject;\r
61528a1b 29import org.tianocore.build.exception.AutoGenException;\r
878ddf1f 30import org.tianocore.build.global.GlobalData;\r
31import org.tianocore.build.global.SurfaceAreaQuery;\r
a29c47e0 32import org.tianocore.build.id.ModuleIdentification;\r
61528a1b 33import org.tianocore.common.exception.EdkException;\r
192a42b4 34import org.tianocore.common.logger.EdkLog;\r
878ddf1f 35/**\r
36 This class This class is to reorder library instance sequence according to\r
37 library dependence.\r
38**/\r
39public class AutogenLibOrder {\r
40 ///\r
41 /// The map of library class and its library instance.\r
42 ///\r
a29c47e0 43 private Map<String, ModuleIdentification> libClassMap = new HashMap<String, ModuleIdentification>();\r
878ddf1f 44\r
45 ///\r
a29c47e0 46 /// The map of library instance and its implemet libraryClass.\r
878ddf1f 47 ///\r
a29c47e0 48 private Map<ModuleIdentification, String[]> libInstanceMap = new HashMap<ModuleIdentification, String[]>();\r
878ddf1f 49\r
50 ///\r
51 /// List of library instance. It is String[3] list, String[0] is libraryName,\r
52 /// String[1] is libraryConstructor name, String[2] is libDestructor name.\r
53 ///\r
a29c47e0 54 private List<LibraryInstanceNode> libInstanceList = new ArrayList<LibraryInstanceNode>();\r
878ddf1f 55 \r
56 /**\r
57 Constructor function\r
58 \r
59 This function mainly initialize some member variable.\r
60 \r
61 @param libraryList List of the library instance.\r
62 @throws Exception\r
63 **/\r
61528a1b 64 AutogenLibOrder(ModuleIdentification[] libraryList, String arch) throws EdkException {\r
a29c47e0 65 LibraryInstanceNode libInstanceNode;\r
66 String[] libClassDeclList = null;\r
67 String[] libClassConsmList = null;\r
878ddf1f 68 \r
a29c47e0 69 for (int i = 0; i < libraryList.length; i++) {\r
878ddf1f 70 //\r
71 // Add libraryInstance in to libInstanceList.\r
a29c47e0 72 // \r
73 Map<String, XmlObject> libDoc = GlobalData.getDoc(libraryList[i], arch);\r
83fba802 74 SurfaceAreaQuery saq = new SurfaceAreaQuery(libDoc);\r
75 libInstanceNode = new LibraryInstanceNode (libraryList[i],saq.getLibConstructorName(), saq.getLibDestructorName());\r
a29c47e0 76 libInstanceList.add(libInstanceNode);\r
878ddf1f 77 \r
78 //\r
79 // Add library instance and consumed library class list to\r
80 // libInstanceMap.\r
81 //\r
83fba802 82 libClassConsmList = saq.getLibraryClasses(CommonDefinition.ALWAYSCONSUMED, arch);\r
878ddf1f 83 if (libClassConsmList != null) {\r
84 String[] classStr = new String[libClassConsmList.length];\r
85 for (int k = 0; k < libClassConsmList.length; k++) {\r
a29c47e0 86 classStr[k] = libClassConsmList[k];\r
878ddf1f 87 }\r
a29c47e0 88 if (this.libInstanceMap.containsKey(libraryList[i])) {\r
61528a1b 89 throw new AutoGenException(\r
a29c47e0 90 libraryList[i].getName()\r
61528a1b 91 + "-- this library instance already exists, please check the library instance list!");\r
878ddf1f 92 } else {\r
a29c47e0 93 this.libInstanceMap.put(libraryList[i], classStr);\r
878ddf1f 94 }\r
95 }\r
96\r
97 //\r
98 // Add library class and library instance map.\r
99 //\r
83fba802 100 libClassDeclList = saq.getLibraryClasses(CommonDefinition.ALWAYSPRODUCED, arch);\r
878ddf1f 101 if (libClassDeclList != null) {\r
102 for (int j = 0; j < libClassDeclList.length; j++) {\r
a29c47e0 103 if (this.libClassMap.containsKey(libClassDeclList[j])) {\r
192a42b4 104 EdkLog.log(EdkLog.EDK_ERROR,libClassDeclList[j]\r
878ddf1f 105 + " class is already implement by "\r
a29c47e0 106 + this.libClassMap.get(libClassDeclList[j]));\r
61528a1b 107 throw new AutoGenException("Library Class: " + libClassDeclList\r
391dbbb1 108 + " already has a library instance!");\r
878ddf1f 109 } else {\r
a29c47e0 110 this.libClassMap.put(libClassDeclList[j], libraryList[i]);\r
878ddf1f 111 }\r
112 }\r
113 }\r
878ddf1f 114 }\r
878ddf1f 115 }\r
116\r
117 /**\r
118 orderLibInstance\r
119 \r
120 This function reorder the library instance according the library class \r
121 dependency.\r
122 \r
123 @return List which content the ordered library instance.\r
124 **/\r
3dc87a3e 125 List<ModuleIdentification> orderLibInstance() {\r
126 LinkedList<ModuleIdentification> orderList = new LinkedList<ModuleIdentification>();\r
127 for (int i = 0; i < libInstanceList.size(); ++i) {\r
128 ModuleIdentification current = libInstanceList.get(i).libId;\r
129 int insertPoint = orderList.size();\r
2c0bc1a2 130 //\r
131 // check current library instance against orderred ones in orderList\r
132 // \r
3dc87a3e 133 for (int j = 0; j < orderList.size(); ++j) {\r
134 ModuleIdentification old = orderList.get(j);\r
3dc87a3e 135 if (consumes(current, old)) {\r
2c0bc1a2 136 //\r
137 // if current library instance consumes the one in orderList\r
138 // it must be put after\r
139 // \r
3dc87a3e 140 insertPoint = j + 1;\r
141 } else if (consumes(old, current)) {\r
2c0bc1a2 142 //\r
143 // if current library instance is consumed by the one in orderList\r
144 // it must be put before. And no further check is needed.\r
145 // \r
3dc87a3e 146 insertPoint = j;\r
147 break;\r
148 }\r
149 }\r
150 orderList.add(insertPoint, current);\r
3dc87a3e 151 }\r
152\r
153 return orderList;\r
154 }\r
155\r
2c0bc1a2 156 //\r
157 // Test if one library consumes another library\r
158 // \r
159 private boolean consumes(ModuleIdentification lib1, ModuleIdentification lib2) {\r
3dc87a3e 160 LinkedList<ModuleIdentification> stack = new LinkedList<ModuleIdentification>();\r
2c0bc1a2 161\r
3dc87a3e 162 stack.add(lib1);\r
163 int j = 0;\r
164 while (j < stack.size()) {\r
2c0bc1a2 165 //\r
166 // get the last library instance in stack, which hasn't been checked\r
167 // \r
3dc87a3e 168 ModuleIdentification lib = stack.get(j++);\r
2c0bc1a2 169 //\r
170 // get the library classes consumed by it\r
171 // \r
3dc87a3e 172 String[] consumedClasses = libInstanceMap.get(lib);\r
173 for (int i = 0; i < consumedClasses.length; ++i) {\r
2c0bc1a2 174 //\r
175 // for each library class, find its corresponding library instance\r
176 // \r
3dc87a3e 177 ModuleIdentification consumedLib = libClassMap.get(consumedClasses[i]);\r
2c0bc1a2 178 //\r
179 // if the corresponding instance is the "lib2", we can say that\r
180 // "lib1" consumes "lib2"\r
181 // \r
3dc87a3e 182 if (consumedLib == lib2) {\r
2c0bc1a2 183 EdkLog.log(EdkLog.EDK_DEBUG, lib1 + "\n consumes\n" + lib2 + "\n");\r
3dc87a3e 184 return true;\r
185 }\r
2c0bc1a2 186 //\r
187 // otherwise, we put it back into the stack to check it later\r
188 // to see if it consumes "lib2" or not. If the library instance\r
189 // consumed by "lib1" consumes "lib2", we can also say that "lib1"\r
190 // consumes "lib2"\r
191 // \r
3dc87a3e 192 if (consumedLib != null && !stack.contains(consumedLib)) {\r
193 stack.offer(consumedLib);\r
2c0bc1a2 194 } else if (consumedLib == lib1) {\r
195 //\r
196 // found circular consume, do nothing now but just print\r
197 // out message for debugging\r
198 // \r
199 String msg = "!!! Library consumes circularly: ";\r
200 for (int k = 0; k < j; k++) {\r
201 msg += stack.get(k).getName() + "->";\r
202 }\r
203 msg += lib1.getName();\r
204 EdkLog.log(EdkLog.EDK_DEBUG, msg);\r
3dc87a3e 205 }\r
206 }\r
207 }\r
208 return false;\r
209 }\r
210\r
878ddf1f 211 /**\r
212 isInLibInstance\r
213 \r
214 This function check does the library instance already in the list.\r
215 \r
216 @param list List of the library instance.\r
217 @param instanceName Name of library instance.\r
218 @return "true" the library instance in list |\r
219 "false" the library instance is not in list.\r
220 **/\r
a29c47e0 221 private boolean isInLibInstance(List<ModuleIdentification> list, ModuleIdentification instanceId) {\r
878ddf1f 222 for (int i = 0; i < list.size(); i++) {\r
a29c47e0 223 \r
224 if (instanceId.equals(list.get(i))) {\r
878ddf1f 225 return true;\r
226 }\r
227 }\r
228 return false;\r
229 }\r
230\r
231 /**\r
232 isInStackList \r
233 \r
234 This function check if the node already in the stack.\r
235 \r
236 @param list Stack.\r
237 @param nodeName Name of node.\r
238 @return "true" if node have in stack |\r
239 "false" if node don't in stack.\r
240 **/ \r
a29c47e0 241 private boolean isInStackList(List<Node> list, ModuleIdentification instanceId) {\r
878ddf1f 242 for (int i = 0; i < list.size(); i++) {\r
a29c47e0 243 if (instanceId.equals(list.get(i).nodeId)) {\r
878ddf1f 244 return true;\r
245 }\r
246 }\r
247 return false;\r
248 }\r
249 \r
250 /**\r
251 isHaveConsDestructor\r
252 \r
253 This function check if the library have constructor or destructor \r
254 function.\r
255 \r
256 @param libName Name of library\r
257 @return "true" if library have constructor or desconstructor |\r
258 "false" if library don't have constructor \r
259 and desconstructor.\r
260 **/\r
a29c47e0 261 private boolean isHaveConsDestructor (ModuleIdentification libNode){\r
878ddf1f 262 for (int i = 0; i < libInstanceList.size(); i++){\r
a29c47e0 263 if (libInstanceList.get(i).libId.equals(libNode)){\r
264 if (libInstanceList.get(i).constructorName != null || libInstanceList.get(i).deconstructorName != null){\r
878ddf1f 265 return true;\r
266 }\r
267 }\r
268 }\r
269 return false;\r
270 }\r
271}\r
272\r
273/**\r
274 Node \r
275 \r
276 This class is used as stack node.\r
277 \r
278 **/\r
279class Node {\r
a29c47e0 280 ModuleIdentification nodeId;\r
878ddf1f 281\r
282 boolean isVisit;\r
283\r
a29c47e0 284 Node(ModuleIdentification nodeId, boolean isVisit) {\r
285 this.nodeId = nodeId;\r
878ddf1f 286 this.isVisit = false;\r
287 }\r
a29c47e0 288} \r
289/**\r
290 LibraryInstance Node \r
291 \r
292 This class is used to store LibrayInstance and it's deconstructor and constructor\r
293**/\r
294 \r
295class LibraryInstanceNode {\r
296 ModuleIdentification libId;\r
297 String deconstructorName;\r
298 String constructorName;\r
299 \r
300 LibraryInstanceNode (ModuleIdentification libId, String deconstructor, String constructor){\r
301 this.libId = libId;\r
302 this.deconstructorName = deconstructor;\r
303 this.constructorName = constructor;\r
304 }\r
305}\r