]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Java/Source/GenBuild/org/tianocore/build/autogen/AutogenLibOrder.java
Fixed an Autogen issue which will cause build break when encountering some kind of...
[mirror_edk2.git] / Tools / Java / Source / GenBuild / org / tianocore / build / autogen / AutogenLibOrder.java
CommitLineData
878ddf1f 1/**@file\r
2 AutogenLibOrder class.\r
3\r
e360ea4d 4 This class is to reorder library instance sequence according to library\r
878ddf1f 5 dependence.\r
e360ea4d 6\r
878ddf1f 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
e360ea4d 12\r
878ddf1f 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
bc33b23d 43 private Map<String, ModuleIdentification> libClassProducer = new HashMap<String, ModuleIdentification>();\r
878ddf1f 44\r
45 ///\r
bc33b23d 46 /// The map of library instance and its consumed Library Classes.\r
878ddf1f 47 ///\r
bc33b23d 48 private Map<ModuleIdentification, String[]> libInstanceConsumes = new HashMap<ModuleIdentification, String[]>();\r
49\r
50 ///\r
51 /// The map of library instance and its implemeted Library Classes.\r
52 ///\r
53 private Map<ModuleIdentification, String[]> libInstanceProduces = new HashMap<ModuleIdentification, String[]>();\r
54\r
55 ///\r
56 /// The map of library instance and its consumers.\r
57 ///\r
58 private Map<ModuleIdentification, HashSet<ModuleIdentification>> libInstanceConsumedBy = new HashMap<ModuleIdentification, HashSet<ModuleIdentification>>();\r
878ddf1f 59\r
60 ///\r
61 /// List of library instance. It is String[3] list, String[0] is libraryName,\r
62 /// String[1] is libraryConstructor name, String[2] is libDestructor name.\r
63 ///\r
bc33b23d 64 private ModuleIdentification[] libInstanceList = null;\r
e360ea4d 65\r
878ddf1f 66 /**\r
67 Constructor function\r
e360ea4d 68\r
878ddf1f 69 This function mainly initialize some member variable.\r
e360ea4d 70\r
878ddf1f 71 @param libraryList List of the library instance.\r
72 @throws Exception\r
73 **/\r
61528a1b 74 AutogenLibOrder(ModuleIdentification[] libraryList, String arch) throws EdkException {\r
bc33b23d 75 ModuleIdentification libInstance;\r
a29c47e0 76 String[] libClassDeclList = null;\r
77 String[] libClassConsmList = null;\r
bc33b23d 78\r
23849470 79 libInstanceList = libraryList;\r
a29c47e0 80 for (int i = 0; i < libraryList.length; i++) {\r
bc33b23d 81 libInstance = libraryList[i];\r
878ddf1f 82 //\r
23849470 83 // Fetch the constructor & destructor.\r
e360ea4d 84 //\r
bc33b23d 85 Map<String, XmlObject> libDoc = GlobalData.getDoc(libInstance, arch);\r
83fba802 86 SurfaceAreaQuery saq = new SurfaceAreaQuery(libDoc);\r
bc33b23d 87 libInstance.setConstructor(saq.getLibConstructorName());\r
88 libInstance.setDestructor(saq.getLibDestructorName());\r
e360ea4d 89\r
878ddf1f 90 //\r
23849470 91 // Create library class consume database.\r
878ddf1f 92 //\r
700279a9 93 libClassConsmList = saq.getLibraryClasses(CommonDefinition.ALWAYSCONSUMED, arch, null);\r
9d3d149f 94 if (libClassConsmList != null) {\r
bc33b23d 95 if (this.libInstanceConsumes.containsKey(libInstance)) {\r
61528a1b 96 throw new AutoGenException(\r
a29c47e0 97 libraryList[i].getName()\r
61528a1b 98 + "-- this library instance already exists, please check the library instance list!");\r
878ddf1f 99 } else {\r
bc33b23d 100 this.libInstanceConsumes.put(libInstance, libClassConsmList);\r
878ddf1f 101 }\r
102 }\r
103\r
104 //\r
23849470 105 // Create library class implementer database\r
878ddf1f 106 //\r
700279a9 107 libClassDeclList = saq.getLibraryClasses(CommonDefinition.ALWAYSPRODUCED, arch, null);\r
9d3d149f 108 if (libClassDeclList != null) {\r
bc33b23d 109 this.libInstanceProduces.put(libInstance, libClassDeclList);\r
878ddf1f 110 for (int j = 0; j < libClassDeclList.length; j++) {\r
bc33b23d 111 if (this.libClassProducer.containsKey(libClassDeclList[j])) {\r
192a42b4 112 EdkLog.log(EdkLog.EDK_ERROR,libClassDeclList[j]\r
bc33b23d 113 + " class is already implemented by "\r
114 + this.libClassProducer.get(libClassDeclList[j]));\r
61528a1b 115 throw new AutoGenException("Library Class: " + libClassDeclList\r
391dbbb1 116 + " already has a library instance!");\r
878ddf1f 117 } else {\r
bc33b23d 118 this.libClassProducer.put(libClassDeclList[j], libInstance);\r
119 }\r
120 }\r
121 }\r
122 }\r
123\r
23849470 124 //\r
e360ea4d 125 // Create a consumed-by database\r
126 //\r
bc33b23d 127 for (Iterator it = libClassProducer.keySet().iterator(); it.hasNext();) {\r
128 String className = (String)it.next();\r
129 libInstance = libClassProducer.get(className);\r
130 libInstanceConsumedBy.put(libInstance, new HashSet<ModuleIdentification>());\r
131\r
132 for (int k = 0; k < libraryList.length; ++k) {\r
133 ModuleIdentification consumer = libraryList[k];\r
134 String[] consumedClassList = libInstanceConsumes.get(consumer);\r
135\r
136 for (int l = 0; l < consumedClassList.length; ++l) {\r
137 if (consumedClassList[l].equals(className)) {\r
138 libInstanceConsumedBy.get(libInstance).add(consumer);\r
878ddf1f 139 }\r
140 }\r
141 }\r
878ddf1f 142 }\r
878ddf1f 143 }\r
144\r
145 /**\r
146 orderLibInstance\r
bc33b23d 147\r
e360ea4d 148 This function reorder the library instance according the library class\r
23849470 149 dependency, using DAG anaylysis algothim\r
bc33b23d 150\r
878ddf1f 151 @return List which content the ordered library instance.\r
152 **/\r
bc33b23d 153 List<ModuleIdentification> orderLibInstance() throws EdkException {\r
3dc87a3e 154 LinkedList<ModuleIdentification> orderList = new LinkedList<ModuleIdentification>();\r
bc33b23d 155 LinkedList<ModuleIdentification> noConsumerList = new LinkedList<ModuleIdentification>();\r
156\r
23849470 157 //\r
158 // First, add the library instance without consumers to the Q\r
e360ea4d 159 //\r
bc33b23d 160 for (int i = 0; i < libInstanceList.length; ++i) {\r
253d2919 161 if (libInstanceList[i] == null) {\r
162 continue;\r
163 }\r
164 \r
165 if (libInstanceConsumedBy.get(libInstanceList[i]) == null || libInstanceConsumedBy.get(libInstanceList[i]).size() == 0) {\r
bc33b23d 166 noConsumerList.add(libInstanceList[i]);\r
3dc87a3e 167 }\r
3dc87a3e 168 }\r
169\r
bc33b23d 170 while (noConsumerList.size() > 0) {\r
171 ModuleIdentification n = noConsumerList.poll();\r
172 orderList.addFirst(n);\r
3dc87a3e 173\r
bc33b23d 174 String[] consumedClassList = libInstanceConsumes.get(n);\r
175 for (int i = 0; i < consumedClassList.length; ++i) {\r
176 ModuleIdentification m = libClassProducer.get(consumedClassList[i]);\r
177 if (m == null) {\r
178 continue;\r
3dc87a3e 179 }\r
bc33b23d 180 HashSet<ModuleIdentification> consumedBy = libInstanceConsumedBy.get(m);\r
253d2919 181 if (consumedBy == null || consumedBy.size() == 0) {\r
e360ea4d 182 continue;\r
183 }\r
184\r
bc33b23d 185 consumedBy.remove(n);\r
186 if (consumedBy.size() == 0) {\r
187 noConsumerList.addLast(m);\r
3dc87a3e 188 }\r
189 }\r
3dc87a3e 190\r
bc33b23d 191 boolean circularlyConsumed = false;\r
192 while (noConsumerList.size() == 0 && !circularlyConsumed) {\r
193 circularlyConsumed = true;\r
194 for (int i = 0; i < libInstanceList.length; ++i) {\r
195 ModuleIdentification libInstance = libInstanceList[i];\r
196 if (!libInstance.hasConstructor()) {\r
197 continue;\r
198 }\r
878ddf1f 199\r
bc33b23d 200 HashSet<ModuleIdentification> consumedBy = libInstanceConsumedBy.get(libInstance);\r
253d2919 201 if (consumedBy == null || consumedBy.size() == 0) {\r
bc33b23d 202 continue;\r
203 }\r
204\r
205 ModuleIdentification[] consumedByList = consumedBy.toArray(new ModuleIdentification[consumedBy.size()]);\r
206 for (int j = 0; j < consumedByList.length; ++j) {\r
207 ModuleIdentification consumer = consumedByList[j];\r
208 if (consumer.hasConstructor()) {\r
209 continue;\r
210 }\r
e360ea4d 211\r
bc33b23d 212 //\r
e360ea4d 213 // if there's no constructor in the library instance's consumer,\r
bc33b23d 214 // remove it from the consumer list\r
e360ea4d 215 //\r
bc33b23d 216 consumedBy.remove(consumer);\r
217 circularlyConsumed = false;\r
218 if (consumedBy.size() == 0) {\r
219 noConsumerList.addLast(libInstance);\r
220 break;\r
221 }\r
222 }\r
223\r
224 if (noConsumerList.size() > 0) {\r
225 break;\r
226 }\r
878ddf1f 227 }\r
e360ea4d 228\r
229 if (noConsumerList.size() == 0 && !circularlyConsumed) {\r
230 break;\r
231 }\r
878ddf1f 232 }\r
233 }\r
878ddf1f 234\r
23849470 235 //\r
236 // Append the remaining library instance to the end of sorted list\r
e360ea4d 237 //\r
700279a9 238 boolean HasError = false;\r
bc33b23d 239 for (int i = 0; i < libInstanceList.length; ++i) {\r
700279a9 240 HashSet<ModuleIdentification> consumedBy = libInstanceConsumedBy.get(libInstanceList[i]);\r
253d2919 241 if (consumedBy != null && consumedBy.size() > 0 && libInstanceList[i].hasConstructor()) {\r
d919bb8c 242 EdkLog.log(EdkLog.EDK_ERROR, libInstanceList[i].getName()\r
243 + " with constructor has a circular dependency!");\r
700279a9 244 ModuleIdentification[] consumedByList = consumedBy.toArray(new ModuleIdentification[consumedBy.size()]);\r
245 for (int j = 0; j < consumedByList.length; ++j) {\r
246 EdkLog.log(EdkLog.EDK_ERROR, " consumed by " + consumedByList[j].getName());\r
247 }\r
248 HasError = true;\r
d919bb8c 249 }\r
250\r
bc33b23d 251 if (!orderList.contains(libInstanceList[i])) {\r
affa5a12 252 orderList.add(libInstanceList[i]);\r
bc33b23d 253 }\r
254 }\r
700279a9 255 if (HasError) {\r
256 throw new AutoGenException("Circular dependency in library instances is found!");\r
257 }\r
b991a451 258\r
bc33b23d 259 return orderList;\r
a29c47e0 260 }\r
261}\r