AutoGen.py 194 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166
  1. ## @file
  2. # Generate AutoGen.h, AutoGen.c and *.depex files
  3. #
  4. # Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
  5. # Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>
  6. # Copyright (c) 2019, American Megatrends, Inc. All rights reserved.<BR>
  7. #
  8. # This program and the accompanying materials
  9. # are licensed and made available under the terms and conditions of the BSD License
  10. # which accompanies this distribution. The full text of the license may be found at
  11. # http://opensource.org/licenses/bsd-license.php
  12. #
  13. # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  14. # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  15. #
  16. ## Import Modules
  17. #
  18. from __future__ import print_function
  19. from __future__ import absolute_import
  20. import Common.LongFilePathOs as os
  21. import re
  22. import os.path as path
  23. import copy
  24. import uuid
  25. from . import GenC
  26. from . import GenMake
  27. from . import GenDepex
  28. from io import BytesIO
  29. from .StrGather import *
  30. from .BuildEngine import BuildRule
  31. import shutil
  32. from Common.LongFilePathSupport import CopyLongFilePath
  33. from Common.BuildToolError import *
  34. from Common.DataType import *
  35. from Common.Misc import *
  36. from Common.StringUtils import *
  37. import Common.GlobalData as GlobalData
  38. from GenFds.FdfParser import *
  39. from CommonDataClass.CommonClass import SkuInfoClass
  40. from GenPatchPcdTable.GenPatchPcdTable import parsePcdInfoFromMapFile
  41. import Common.VpdInfoFile as VpdInfoFile
  42. from .GenPcdDb import CreatePcdDatabaseCode
  43. from Workspace.MetaFileCommentParser import UsageList
  44. from Workspace.WorkspaceCommon import GetModuleLibInstances
  45. from Common.MultipleWorkspace import MultipleWorkspace as mws
  46. from . import InfSectionParser
  47. import datetime
  48. import hashlib
  49. from .GenVar import VariableMgr, var_info
  50. from collections import OrderedDict
  51. from collections import defaultdict
  52. from Workspace.WorkspaceCommon import OrderedListDict
  53. from Common.ToolDefClassObject import gDefaultToolsDefFile
  54. from Common.caching import cached_property, cached_class_function
  55. ## Regular expression for splitting Dependency Expression string into tokens
  56. gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")
  57. ## Regular expression for match: PCD(xxxx.yyy)
  58. gPCDAsGuidPattern = re.compile(r"^PCD\(.+\..+\)$")
  59. #
  60. # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
  61. # is the former use /I , the Latter used -I to specify include directories
  62. #
  63. gBuildOptIncludePatternMsft = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
  64. gBuildOptIncludePatternOther = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)
  65. #
  66. # Match name = variable
  67. #
  68. gEfiVarStoreNamePattern = re.compile("\s*name\s*=\s*(\w+)")
  69. #
  70. # The format of guid in efivarstore statement likes following and must be correct:
  71. # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}
  72. #
  73. gEfiVarStoreGuidPattern = re.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")
  74. ## Mapping Makefile type
  75. gMakeTypeMap = {TAB_COMPILER_MSFT:"nmake", "GCC":"gmake"}
  76. ## Build rule configuration file
  77. gDefaultBuildRuleFile = 'build_rule.txt'
  78. ## Build rule default version
  79. AutoGenReqBuildRuleVerNum = "0.1"
  80. ## default file name for AutoGen
  81. gAutoGenCodeFileName = "AutoGen.c"
  82. gAutoGenHeaderFileName = "AutoGen.h"
  83. gAutoGenStringFileName = "%(module_name)sStrDefs.h"
  84. gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"
  85. gAutoGenDepexFileName = "%(module_name)s.depex"
  86. gAutoGenImageDefFileName = "%(module_name)sImgDefs.h"
  87. gAutoGenIdfFileName = "%(module_name)sIdf.hpk"
  88. gInfSpecVersion = "0x00010017"
  89. #
  90. # Template string to generic AsBuilt INF
  91. #
  92. gAsBuiltInfHeaderString = TemplateString("""${header_comments}
  93. # DO NOT EDIT
  94. # FILE auto-generated
  95. [Defines]
  96. INF_VERSION = ${module_inf_version}
  97. BASE_NAME = ${module_name}
  98. FILE_GUID = ${module_guid}
  99. MODULE_TYPE = ${module_module_type}${BEGIN}
  100. VERSION_STRING = ${module_version_string}${END}${BEGIN}
  101. PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}
  102. UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}
  103. PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}
  104. ENTRY_POINT = ${module_entry_point}${END}${BEGIN}
  105. UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}
  106. CONSTRUCTOR = ${module_constructor}${END}${BEGIN}
  107. DESTRUCTOR = ${module_destructor}${END}${BEGIN}
  108. SHADOW = ${module_shadow}${END}${BEGIN}
  109. PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}
  110. PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}
  111. PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}
  112. PCI_REVISION = ${module_pci_revision}${END}${BEGIN}
  113. BUILD_NUMBER = ${module_build_number}${END}${BEGIN}
  114. SPEC = ${module_spec}${END}${BEGIN}
  115. UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}
  116. MODULE_UNI_FILE = ${module_uni_file}${END}
  117. [Packages.${module_arch}]${BEGIN}
  118. ${package_item}${END}
  119. [Binaries.${module_arch}]${BEGIN}
  120. ${binary_item}${END}
  121. [PatchPcd.${module_arch}]${BEGIN}
  122. ${patchablepcd_item}
  123. ${END}
  124. [Protocols.${module_arch}]${BEGIN}
  125. ${protocol_item}
  126. ${END}
  127. [Ppis.${module_arch}]${BEGIN}
  128. ${ppi_item}
  129. ${END}
  130. [Guids.${module_arch}]${BEGIN}
  131. ${guid_item}
  132. ${END}
  133. [PcdEx.${module_arch}]${BEGIN}
  134. ${pcd_item}
  135. ${END}
  136. [LibraryClasses.${module_arch}]
  137. ## @LIB_INSTANCES${BEGIN}
  138. # ${libraryclasses_item}${END}
  139. ${depexsection_item}
  140. ${userextension_tianocore_item}
  141. ${tail_comments}
  142. [BuildOptions.${module_arch}]
  143. ## @AsBuilt${BEGIN}
  144. ## ${flags_item}${END}
  145. """)
  146. ## Split command line option string to list
  147. #
  148. # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
  149. # in non-windows platform to launch command
  150. #
  151. def _SplitOption(OptionString):
  152. OptionList = []
  153. LastChar = " "
  154. OptionStart = 0
  155. QuotationMark = ""
  156. for Index in range(0, len(OptionString)):
  157. CurrentChar = OptionString[Index]
  158. if CurrentChar in ['"', "'"]:
  159. if QuotationMark == CurrentChar:
  160. QuotationMark = ""
  161. elif QuotationMark == "":
  162. QuotationMark = CurrentChar
  163. continue
  164. elif QuotationMark:
  165. continue
  166. if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:
  167. if Index > OptionStart:
  168. OptionList.append(OptionString[OptionStart:Index - 1])
  169. OptionStart = Index
  170. LastChar = CurrentChar
  171. OptionList.append(OptionString[OptionStart:])
  172. return OptionList
  173. #
  174. # Convert string to C format array
  175. #
  176. def _ConvertStringToByteArray(Value):
  177. Value = Value.strip()
  178. if not Value:
  179. return None
  180. if Value[0] == '{':
  181. if not Value.endswith('}'):
  182. return None
  183. Value = Value.replace(' ', '').replace('{', '').replace('}', '')
  184. ValFields = Value.split(',')
  185. try:
  186. for Index in range(len(ValFields)):
  187. ValFields[Index] = str(int(ValFields[Index], 0))
  188. except ValueError:
  189. return None
  190. Value = '{' + ','.join(ValFields) + '}'
  191. return Value
  192. Unicode = False
  193. if Value.startswith('L"'):
  194. if not Value.endswith('"'):
  195. return None
  196. Value = Value[1:]
  197. Unicode = True
  198. elif not Value.startswith('"') or not Value.endswith('"'):
  199. return None
  200. Value = eval(Value) # translate escape character
  201. NewValue = '{'
  202. for Index in range(0, len(Value)):
  203. if Unicode:
  204. NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ','
  205. else:
  206. NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ','
  207. Value = NewValue + '0}'
  208. return Value
  209. ## Base class for AutoGen
  210. #
  211. # This class just implements the cache mechanism of AutoGen objects.
  212. #
  213. class AutoGen(object):
  214. # database to maintain the objects in each child class
  215. __ObjectCache = {} # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object
  216. ## Factory method
  217. #
  218. # @param Class class object of real AutoGen class
  219. # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)
  220. # @param Workspace Workspace directory or WorkspaceAutoGen object
  221. # @param MetaFile The path of meta file
  222. # @param Target Build target
  223. # @param Toolchain Tool chain name
  224. # @param Arch Target arch
  225. # @param *args The specific class related parameters
  226. # @param **kwargs The specific class related dict parameters
  227. #
  228. def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
  229. # check if the object has been created
  230. Key = (Target, Toolchain, Arch, MetaFile)
  231. if Key in cls.__ObjectCache:
  232. # if it exists, just return it directly
  233. return cls.__ObjectCache[Key]
  234. # it didnt exist. create it, cache it, then return it
  235. RetVal = cls.__ObjectCache[Key] = super(AutoGen, cls).__new__(cls)
  236. return RetVal
  237. ## hash() operator
  238. #
  239. # The file path of platform file will be used to represent hash value of this object
  240. #
  241. # @retval int Hash value of the file path of platform file
  242. #
  243. def __hash__(self):
  244. return hash(self.MetaFile)
  245. ## str() operator
  246. #
  247. # The file path of platform file will be used to represent this object
  248. #
  249. # @retval string String of platform file path
  250. #
  251. def __str__(self):
  252. return str(self.MetaFile)
  253. ## "==" operator
  254. def __eq__(self, Other):
  255. return Other and self.MetaFile == Other
  256. ## Workspace AutoGen class
  257. #
  258. # This class is used mainly to control the whole platform build for different
  259. # architecture. This class will generate top level makefile.
  260. #
  261. class WorkspaceAutoGen(AutoGen):
  262. # call super().__init__ then call the worker function with different parameter count
  263. def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
  264. if not hasattr(self, "_Init"):
  265. self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)
  266. self._Init = True
  267. ## Initialize WorkspaceAutoGen
  268. #
  269. # @param WorkspaceDir Root directory of workspace
  270. # @param ActivePlatform Meta-file of active platform
  271. # @param Target Build target
  272. # @param Toolchain Tool chain name
  273. # @param ArchList List of architecture of current build
  274. # @param MetaFileDb Database containing meta-files
  275. # @param BuildConfig Configuration of build
  276. # @param ToolDefinition Tool chain definitions
  277. # @param FlashDefinitionFile File of flash definition
  278. # @param Fds FD list to be generated
  279. # @param Fvs FV list to be generated
  280. # @param Caps Capsule list to be generated
  281. # @param SkuId SKU id from command line
  282. #
  283. def _InitWorker(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,
  284. BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=None, Fvs=None, Caps=None, SkuId='', UniFlag=None,
  285. Progress=None, BuildModule=None):
  286. self.BuildDatabase = MetaFileDb
  287. self.MetaFile = ActivePlatform
  288. self.WorkspaceDir = WorkspaceDir
  289. self.Platform = self.BuildDatabase[self.MetaFile, TAB_ARCH_COMMON, Target, Toolchain]
  290. GlobalData.gActivePlatform = self.Platform
  291. self.BuildTarget = Target
  292. self.ToolChain = Toolchain
  293. self.ArchList = ArchList
  294. self.SkuId = SkuId
  295. self.UniFlag = UniFlag
  296. self.TargetTxt = BuildConfig
  297. self.ToolDef = ToolDefinition
  298. self.FdfFile = FlashDefinitionFile
  299. self.FdTargetList = Fds if Fds else []
  300. self.FvTargetList = Fvs if Fvs else []
  301. self.CapTargetList = Caps if Caps else []
  302. self.AutoGenObjectList = []
  303. self._GuidDict = {}
  304. # there's many relative directory operations, so ...
  305. os.chdir(self.WorkspaceDir)
  306. #
  307. # Merge Arch
  308. #
  309. if not self.ArchList:
  310. ArchList = set(self.Platform.SupArchList)
  311. else:
  312. ArchList = set(self.ArchList) & set(self.Platform.SupArchList)
  313. if not ArchList:
  314. EdkLogger.error("build", PARAMETER_INVALID,
  315. ExtraData = "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self.Platform.SupArchList)))
  316. elif self.ArchList and len(ArchList) != len(self.ArchList):
  317. SkippedArchList = set(self.ArchList).symmetric_difference(set(self.Platform.SupArchList))
  318. EdkLogger.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"
  319. % (" ".join(SkippedArchList), " ".join(self.Platform.SupArchList)))
  320. self.ArchList = tuple(ArchList)
  321. # Validate build target
  322. if self.BuildTarget not in self.Platform.BuildTargets:
  323. EdkLogger.error("build", PARAMETER_INVALID,
  324. ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"
  325. % (self.BuildTarget, " ".join(self.Platform.BuildTargets)))
  326. # parse FDF file to get PCDs in it, if any
  327. if not self.FdfFile:
  328. self.FdfFile = self.Platform.FlashDefinition
  329. EdkLogger.info("")
  330. if self.ArchList:
  331. EdkLogger.info('%-16s = %s' % ("Architecture(s)", ' '.join(self.ArchList)))
  332. EdkLogger.info('%-16s = %s' % ("Build target", self.BuildTarget))
  333. EdkLogger.info('%-16s = %s' % ("Toolchain", self.ToolChain))
  334. EdkLogger.info('\n%-24s = %s' % ("Active Platform", self.Platform))
  335. if BuildModule:
  336. EdkLogger.info('%-24s = %s' % ("Active Module", BuildModule))
  337. if self.FdfFile:
  338. EdkLogger.info('%-24s = %s' % ("Flash Image Definition", self.FdfFile))
  339. EdkLogger.verbose("\nFLASH_DEFINITION = %s" % self.FdfFile)
  340. if Progress:
  341. Progress.Start("\nProcessing meta-data")
  342. if self.FdfFile:
  343. #
  344. # Mark now build in AutoGen Phase
  345. #
  346. GlobalData.gAutoGenPhase = True
  347. Fdf = FdfParser(self.FdfFile.Path)
  348. Fdf.ParseFile()
  349. GlobalData.gFdfParser = Fdf
  350. GlobalData.gAutoGenPhase = False
  351. PcdSet = Fdf.Profile.PcdDict
  352. if Fdf.CurrentFdName and Fdf.CurrentFdName in Fdf.Profile.FdDict:
  353. FdDict = Fdf.Profile.FdDict[Fdf.CurrentFdName]
  354. for FdRegion in FdDict.RegionList:
  355. if str(FdRegion.RegionType) is 'FILE' and self.Platform.VpdToolGuid in str(FdRegion.RegionDataList):
  356. if int(FdRegion.Offset) % 8 != 0:
  357. EdkLogger.error("build", FORMAT_INVALID, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion.Offset))
  358. ModuleList = Fdf.Profile.InfList
  359. self.FdfProfile = Fdf.Profile
  360. for fvname in self.FvTargetList:
  361. if fvname.upper() not in self.FdfProfile.FvDict:
  362. EdkLogger.error("build", OPTION_VALUE_INVALID,
  363. "No such an FV in FDF file: %s" % fvname)
  364. # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,
  365. # but the path (self.MetaFile.Path) is the real path
  366. for key in self.FdfProfile.InfDict:
  367. if key == 'ArchTBD':
  368. MetaFile_cache = defaultdict(set)
  369. for Arch in self.ArchList:
  370. Current_Platform_cache = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]
  371. for Pkey in Current_Platform_cache.Modules:
  372. MetaFile_cache[Arch].add(Current_Platform_cache.Modules[Pkey].MetaFile)
  373. for Inf in self.FdfProfile.InfDict[key]:
  374. ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
  375. for Arch in self.ArchList:
  376. if ModuleFile in MetaFile_cache[Arch]:
  377. break
  378. else:
  379. ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]
  380. if not ModuleData.IsBinaryModule:
  381. EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)
  382. else:
  383. for Arch in self.ArchList:
  384. if Arch == key:
  385. Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]
  386. MetaFileList = set()
  387. for Pkey in Platform.Modules:
  388. MetaFileList.add(Platform.Modules[Pkey].MetaFile)
  389. for Inf in self.FdfProfile.InfDict[key]:
  390. ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
  391. if ModuleFile in MetaFileList:
  392. continue
  393. ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]
  394. if not ModuleData.IsBinaryModule:
  395. EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)
  396. else:
  397. PcdSet = {}
  398. ModuleList = []
  399. self.FdfProfile = None
  400. if self.FdTargetList:
  401. EdkLogger.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self.FdTargetList))
  402. self.FdTargetList = []
  403. if self.FvTargetList:
  404. EdkLogger.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self.FvTargetList))
  405. self.FvTargetList = []
  406. if self.CapTargetList:
  407. EdkLogger.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self.CapTargetList))
  408. self.CapTargetList = []
  409. # apply SKU and inject PCDs from Flash Definition file
  410. for Arch in self.ArchList:
  411. Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]
  412. PlatformPcds = Platform.Pcds
  413. self._GuidDict = Platform._GuidDict
  414. SourcePcdDict = {TAB_PCDS_DYNAMIC_EX:set(), TAB_PCDS_PATCHABLE_IN_MODULE:set(),TAB_PCDS_DYNAMIC:set(),TAB_PCDS_FIXED_AT_BUILD:set()}
  415. BinaryPcdDict = {TAB_PCDS_DYNAMIC_EX:set(), TAB_PCDS_PATCHABLE_IN_MODULE:set()}
  416. SourcePcdDict_Keys = SourcePcdDict.keys()
  417. BinaryPcdDict_Keys = BinaryPcdDict.keys()
  418. # generate the SourcePcdDict and BinaryPcdDict
  419. PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
  420. for BuildData in list(PGen.BuildDatabase._CACHE_.values()):
  421. if BuildData.Arch != Arch:
  422. continue
  423. if BuildData.MetaFile.Ext == '.inf':
  424. for key in BuildData.Pcds:
  425. if BuildData.Pcds[key].Pending:
  426. if key in Platform.Pcds:
  427. PcdInPlatform = Platform.Pcds[key]
  428. if PcdInPlatform.Type:
  429. BuildData.Pcds[key].Type = PcdInPlatform.Type
  430. BuildData.Pcds[key].Pending = False
  431. if BuildData.MetaFile in Platform.Modules:
  432. PlatformModule = Platform.Modules[str(BuildData.MetaFile)]
  433. if key in PlatformModule.Pcds:
  434. PcdInPlatform = PlatformModule.Pcds[key]
  435. if PcdInPlatform.Type:
  436. BuildData.Pcds[key].Type = PcdInPlatform.Type
  437. BuildData.Pcds[key].Pending = False
  438. else:
  439. #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending
  440. if BuildData.Pcds[key].Pending:
  441. MGen = ModuleAutoGen(self, BuildData.MetaFile, Target, Toolchain, Arch, self.MetaFile)
  442. if MGen and MGen.IsLibrary:
  443. if MGen in PGen.LibraryAutoGenList:
  444. ReferenceModules = MGen.ReferenceModules
  445. for ReferenceModule in ReferenceModules:
  446. if ReferenceModule.MetaFile in Platform.Modules:
  447. RefPlatformModule = Platform.Modules[str(ReferenceModule.MetaFile)]
  448. if key in RefPlatformModule.Pcds:
  449. PcdInReferenceModule = RefPlatformModule.Pcds[key]
  450. if PcdInReferenceModule.Type:
  451. BuildData.Pcds[key].Type = PcdInReferenceModule.Type
  452. BuildData.Pcds[key].Pending = False
  453. break
  454. if TAB_PCDS_DYNAMIC_EX in BuildData.Pcds[key].Type:
  455. if BuildData.IsBinaryModule:
  456. BinaryPcdDict[TAB_PCDS_DYNAMIC_EX].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
  457. else:
  458. SourcePcdDict[TAB_PCDS_DYNAMIC_EX].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
  459. elif TAB_PCDS_PATCHABLE_IN_MODULE in BuildData.Pcds[key].Type:
  460. if BuildData.MetaFile.Ext == '.inf':
  461. if BuildData.IsBinaryModule:
  462. BinaryPcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
  463. else:
  464. SourcePcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
  465. elif TAB_PCDS_DYNAMIC in BuildData.Pcds[key].Type:
  466. SourcePcdDict[TAB_PCDS_DYNAMIC].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
  467. elif TAB_PCDS_FIXED_AT_BUILD in BuildData.Pcds[key].Type:
  468. SourcePcdDict[TAB_PCDS_FIXED_AT_BUILD].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))
  469. else:
  470. pass
  471. #
  472. # A PCD can only use one type for all source modules
  473. #
  474. for i in SourcePcdDict_Keys:
  475. for j in SourcePcdDict_Keys:
  476. if i != j:
  477. Intersections = SourcePcdDict[i].intersection(SourcePcdDict[j])
  478. if len(Intersections) > 0:
  479. EdkLogger.error(
  480. 'build',
  481. FORMAT_INVALID,
  482. "Building modules from source INFs, following PCD use %s and %s access method. It must be corrected to use only one access method." % (i, j),
  483. ExtraData='\n\t'.join(str(P[1]+'.'+P[0]) for P in Intersections)
  484. )
  485. #
  486. # intersection the BinaryPCD for Mixed PCD
  487. #
  488. for i in BinaryPcdDict_Keys:
  489. for j in BinaryPcdDict_Keys:
  490. if i != j:
  491. Intersections = BinaryPcdDict[i].intersection(BinaryPcdDict[j])
  492. for item in Intersections:
  493. NewPcd1 = (item[0] + '_' + i, item[1])
  494. NewPcd2 = (item[0] + '_' + j, item[1])
  495. if item not in GlobalData.MixedPcd:
  496. GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]
  497. else:
  498. if NewPcd1 not in GlobalData.MixedPcd[item]:
  499. GlobalData.MixedPcd[item].append(NewPcd1)
  500. if NewPcd2 not in GlobalData.MixedPcd[item]:
  501. GlobalData.MixedPcd[item].append(NewPcd2)
  502. #
  503. # intersection the SourcePCD and BinaryPCD for Mixed PCD
  504. #
  505. for i in SourcePcdDict_Keys:
  506. for j in BinaryPcdDict_Keys:
  507. if i != j:
  508. Intersections = SourcePcdDict[i].intersection(BinaryPcdDict[j])
  509. for item in Intersections:
  510. NewPcd1 = (item[0] + '_' + i, item[1])
  511. NewPcd2 = (item[0] + '_' + j, item[1])
  512. if item not in GlobalData.MixedPcd:
  513. GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]
  514. else:
  515. if NewPcd1 not in GlobalData.MixedPcd[item]:
  516. GlobalData.MixedPcd[item].append(NewPcd1)
  517. if NewPcd2 not in GlobalData.MixedPcd[item]:
  518. GlobalData.MixedPcd[item].append(NewPcd2)
  519. for BuildData in PGen.BuildDatabase._CACHE_.values():
  520. if BuildData.Arch != Arch:
  521. continue
  522. for key in BuildData.Pcds:
  523. for SinglePcd in GlobalData.MixedPcd:
  524. if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) == SinglePcd:
  525. for item in GlobalData.MixedPcd[SinglePcd]:
  526. Pcd_Type = item[0].split('_')[-1]
  527. if (Pcd_Type == BuildData.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and BuildData.Pcds[key].Type in PCD_DYNAMIC_EX_TYPE_SET) or \
  528. (Pcd_Type == TAB_PCDS_DYNAMIC and BuildData.Pcds[key].Type in PCD_DYNAMIC_TYPE_SET):
  529. Value = BuildData.Pcds[key]
  530. Value.TokenCName = BuildData.Pcds[key].TokenCName + '_' + Pcd_Type
  531. if len(key) == 2:
  532. newkey = (Value.TokenCName, key[1])
  533. elif len(key) == 3:
  534. newkey = (Value.TokenCName, key[1], key[2])
  535. del BuildData.Pcds[key]
  536. BuildData.Pcds[newkey] = Value
  537. break
  538. break
  539. # handle the mixed pcd in FDF file
  540. for key in PcdSet:
  541. if key in GlobalData.MixedPcd:
  542. Value = PcdSet[key]
  543. del PcdSet[key]
  544. for item in GlobalData.MixedPcd[key]:
  545. PcdSet[item] = Value
  546. #Collect package set information from INF of FDF
  547. PkgSet = set()
  548. for Inf in ModuleList:
  549. ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)
  550. if ModuleFile in Platform.Modules:
  551. continue
  552. ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]
  553. PkgSet.update(ModuleData.Packages)
  554. Pkgs = list(PkgSet) + list(PGen.PackageList)
  555. DecPcds = set()
  556. DecPcdsKey = set()
  557. for Pkg in Pkgs:
  558. for Pcd in Pkg.Pcds:
  559. DecPcds.add((Pcd[0], Pcd[1]))
  560. DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))
  561. Platform.SkuName = self.SkuId
  562. for Name, Guid,Fileds in PcdSet:
  563. if (Name, Guid) not in DecPcds:
  564. EdkLogger.error(
  565. 'build',
  566. PARSER_ERROR,
  567. "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid, Name),
  568. File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],
  569. Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]
  570. )
  571. else:
  572. # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.
  573. if (Name, Guid, TAB_PCDS_FIXED_AT_BUILD) in DecPcdsKey \
  574. or (Name, Guid, TAB_PCDS_PATCHABLE_IN_MODULE) in DecPcdsKey \
  575. or (Name, Guid, TAB_PCDS_FEATURE_FLAG) in DecPcdsKey:
  576. continue
  577. elif (Name, Guid, TAB_PCDS_DYNAMIC) in DecPcdsKey or (Name, Guid, TAB_PCDS_DYNAMIC_EX) in DecPcdsKey:
  578. EdkLogger.error(
  579. 'build',
  580. PARSER_ERROR,
  581. "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid, Name),
  582. File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],
  583. Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]
  584. )
  585. Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)
  586. #
  587. # Explicitly collect platform's dynamic PCDs
  588. #
  589. Pa.CollectPlatformDynamicPcds()
  590. Pa.CollectFixedAtBuildPcds()
  591. self.AutoGenObjectList.append(Pa)
  592. #
  593. # Generate Package level hash value
  594. #
  595. GlobalData.gPackageHash[Arch] = {}
  596. if GlobalData.gUseHashCache:
  597. for Pkg in Pkgs:
  598. self._GenPkgLevelHash(Pkg)
  599. #
  600. # Check PCDs token value conflict in each DEC file.
  601. #
  602. self._CheckAllPcdsTokenValueConflict()
  603. #
  604. # Check PCD type and definition between DSC and DEC
  605. #
  606. self._CheckPcdDefineAndType()
  607. #
  608. # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.
  609. #
  610. content = 'gCommandLineDefines: '
  611. content += str(GlobalData.gCommandLineDefines)
  612. content += TAB_LINE_BREAK
  613. content += 'BuildOptionPcd: '
  614. content += str(GlobalData.BuildOptionPcd)
  615. content += TAB_LINE_BREAK
  616. content += 'Active Platform: '
  617. content += str(self.Platform)
  618. content += TAB_LINE_BREAK
  619. if self.FdfFile:
  620. content += 'Flash Image Definition: '
  621. content += str(self.FdfFile)
  622. content += TAB_LINE_BREAK
  623. SaveFileOnChange(os.path.join(self.BuildDir, 'BuildOptions'), content, False)
  624. #
  625. # Create PcdToken Number file for Dynamic/DynamicEx Pcd.
  626. #
  627. PcdTokenNumber = 'PcdTokenNumber: '
  628. if Pa.PcdTokenNumber:
  629. if Pa.DynamicPcdList:
  630. for Pcd in Pa.DynamicPcdList:
  631. PcdTokenNumber += TAB_LINE_BREAK
  632. PcdTokenNumber += str((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))
  633. PcdTokenNumber += ' : '
  634. PcdTokenNumber += str(Pa.PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName])
  635. SaveFileOnChange(os.path.join(self.BuildDir, 'PcdTokenNumber'), PcdTokenNumber, False)
  636. #
  637. # Get set of workspace metafiles
  638. #
  639. AllWorkSpaceMetaFiles = self._GetMetaFiles(Target, Toolchain, Arch)
  640. #
  641. # Retrieve latest modified time of all metafiles
  642. #
  643. SrcTimeStamp = 0
  644. for f in AllWorkSpaceMetaFiles:
  645. if os.stat(f)[8] > SrcTimeStamp:
  646. SrcTimeStamp = os.stat(f)[8]
  647. self._SrcTimeStamp = SrcTimeStamp
  648. if GlobalData.gUseHashCache:
  649. m = hashlib.md5()
  650. for files in AllWorkSpaceMetaFiles:
  651. if files.endswith('.dec'):
  652. continue
  653. f = open(files, 'rb')
  654. Content = f.read()
  655. f.close()
  656. m.update(Content)
  657. SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), False)
  658. GlobalData.gPlatformHash = m.hexdigest()
  659. #
  660. # Write metafile list to build directory
  661. #
  662. AutoGenFilePath = os.path.join(self.BuildDir, 'AutoGen')
  663. if os.path.exists (AutoGenFilePath):
  664. os.remove(AutoGenFilePath)
  665. if not os.path.exists(self.BuildDir):
  666. os.makedirs(self.BuildDir)
  667. with open(os.path.join(self.BuildDir, 'AutoGen'), 'w+') as file:
  668. for f in AllWorkSpaceMetaFiles:
  669. print(f, file=file)
  670. return True
  671. def _GenPkgLevelHash(self, Pkg):
  672. if Pkg.PackageName in GlobalData.gPackageHash[Pkg.Arch]:
  673. return
  674. PkgDir = os.path.join(self.BuildDir, Pkg.Arch, Pkg.PackageName)
  675. CreateDirectory(PkgDir)
  676. HashFile = os.path.join(PkgDir, Pkg.PackageName + '.hash')
  677. m = hashlib.md5()
  678. # Get .dec file's hash value
  679. f = open(Pkg.MetaFile.Path, 'rb')
  680. Content = f.read()
  681. f.close()
  682. m.update(Content)
  683. # Get include files hash value
  684. if Pkg.Includes:
  685. for inc in sorted(Pkg.Includes, key=lambda x: str(x)):
  686. for Root, Dirs, Files in os.walk(str(inc)):
  687. for File in sorted(Files):
  688. File_Path = os.path.join(Root, File)
  689. f = open(File_Path, 'rb')
  690. Content = f.read()
  691. f.close()
  692. m.update(Content)
  693. SaveFileOnChange(HashFile, m.hexdigest(), False)
  694. GlobalData.gPackageHash[Pkg.Arch][Pkg.PackageName] = m.hexdigest()
  695. def _GetMetaFiles(self, Target, Toolchain, Arch):
  696. AllWorkSpaceMetaFiles = set()
  697. #
  698. # add fdf
  699. #
  700. if self.FdfFile:
  701. AllWorkSpaceMetaFiles.add (self.FdfFile.Path)
  702. for f in GlobalData.gFdfParser.GetAllIncludedFile():
  703. AllWorkSpaceMetaFiles.add (f.FileName)
  704. #
  705. # add dsc
  706. #
  707. AllWorkSpaceMetaFiles.add(self.MetaFile.Path)
  708. #
  709. # add build_rule.txt & tools_def.txt
  710. #
  711. AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultBuildRuleFile))
  712. AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultToolsDefFile))
  713. # add BuildOption metafile
  714. #
  715. AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'BuildOptions'))
  716. # add PcdToken Number file for Dynamic/DynamicEx Pcd
  717. #
  718. AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'PcdTokenNumber'))
  719. for Arch in self.ArchList:
  720. #
  721. # add dec
  722. #
  723. for Package in PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch).PackageList:
  724. AllWorkSpaceMetaFiles.add(Package.MetaFile.Path)
  725. #
  726. # add included dsc
  727. #
  728. for filePath in self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]._RawData.IncludedFiles:
  729. AllWorkSpaceMetaFiles.add(filePath.Path)
  730. return AllWorkSpaceMetaFiles
  731. def _CheckPcdDefineAndType(self):
  732. PcdTypeSet = {TAB_PCDS_FIXED_AT_BUILD,
  733. TAB_PCDS_PATCHABLE_IN_MODULE,
  734. TAB_PCDS_FEATURE_FLAG,
  735. TAB_PCDS_DYNAMIC,
  736. TAB_PCDS_DYNAMIC_EX}
  737. # This dict store PCDs which are not used by any modules with specified arches
  738. UnusedPcd = OrderedDict()
  739. for Pa in self.AutoGenObjectList:
  740. # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid
  741. for Pcd in Pa.Platform.Pcds:
  742. PcdType = Pa.Platform.Pcds[Pcd].Type
  743. # If no PCD type, this PCD comes from FDF
  744. if not PcdType:
  745. continue
  746. # Try to remove Hii and Vpd suffix
  747. if PcdType.startswith(TAB_PCDS_DYNAMIC_EX):
  748. PcdType = TAB_PCDS_DYNAMIC_EX
  749. elif PcdType.startswith(TAB_PCDS_DYNAMIC):
  750. PcdType = TAB_PCDS_DYNAMIC
  751. for Package in Pa.PackageList:
  752. # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType
  753. if (Pcd[0], Pcd[1], PcdType) in Package.Pcds:
  754. break
  755. for Type in PcdTypeSet:
  756. if (Pcd[0], Pcd[1], Type) in Package.Pcds:
  757. EdkLogger.error(
  758. 'build',
  759. FORMAT_INVALID,
  760. "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \
  761. % (Pa.Platform.Pcds[Pcd].Type, Pcd[1], Pcd[0], Type),
  762. ExtraData=None
  763. )
  764. return
  765. else:
  766. UnusedPcd.setdefault(Pcd, []).append(Pa.Arch)
  767. for Pcd in UnusedPcd:
  768. EdkLogger.warn(
  769. 'build',
  770. "The PCD was not specified by any INF module in the platform for the given architecture.\n"
  771. "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"
  772. % (Pcd[1], Pcd[0], os.path.basename(str(self.MetaFile)), str(UnusedPcd[Pcd])),
  773. ExtraData=None
  774. )
  775. def __repr__(self):
  776. return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))
  777. ## Return the directory to store FV files
  778. @cached_property
  779. def FvDir(self):
  780. return path.join(self.BuildDir, TAB_FV_DIRECTORY)
  781. ## Return the directory to store all intermediate and final files built
  782. @cached_property
  783. def BuildDir(self):
  784. return self.AutoGenObjectList[0].BuildDir
  785. ## Return the build output directory platform specifies
  786. @cached_property
  787. def OutputDir(self):
  788. return self.Platform.OutputDirectory
  789. ## Return platform name
  790. @cached_property
  791. def Name(self):
  792. return self.Platform.PlatformName
  793. ## Return meta-file GUID
  794. @cached_property
  795. def Guid(self):
  796. return self.Platform.Guid
  797. ## Return platform version
  798. @cached_property
  799. def Version(self):
  800. return self.Platform.Version
  801. ## Return paths of tools
  802. @cached_property
  803. def ToolDefinition(self):
  804. return self.AutoGenObjectList[0].ToolDefinition
  805. ## Return directory of platform makefile
  806. #
  807. # @retval string Makefile directory
  808. #
  809. @cached_property
  810. def MakeFileDir(self):
  811. return self.BuildDir
  812. ## Return build command string
  813. #
  814. # @retval string Build command string
  815. #
  816. @cached_property
  817. def BuildCommand(self):
  818. # BuildCommand should be all the same. So just get one from platform AutoGen
  819. return self.AutoGenObjectList[0].BuildCommand
  820. ## Check the PCDs token value conflict in each DEC file.
  821. #
  822. # Will cause build break and raise error message while two PCDs conflict.
  823. #
  824. # @return None
  825. #
  826. def _CheckAllPcdsTokenValueConflict(self):
  827. for Pa in self.AutoGenObjectList:
  828. for Package in Pa.PackageList:
  829. PcdList = list(Package.Pcds.values())
  830. PcdList.sort(key=lambda x: int(x.TokenValue, 0))
  831. Count = 0
  832. while (Count < len(PcdList) - 1) :
  833. Item = PcdList[Count]
  834. ItemNext = PcdList[Count + 1]
  835. #
  836. # Make sure in the same token space the TokenValue should be unique
  837. #
  838. if (int(Item.TokenValue, 0) == int(ItemNext.TokenValue, 0)):
  839. SameTokenValuePcdList = []
  840. SameTokenValuePcdList.append(Item)
  841. SameTokenValuePcdList.append(ItemNext)
  842. RemainPcdListLength = len(PcdList) - Count - 2
  843. for ValueSameCount in range(RemainPcdListLength):
  844. if int(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue, 0) == int(Item.TokenValue, 0):
  845. SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])
  846. else:
  847. break;
  848. #
  849. # Sort same token value PCD list with TokenGuid and TokenCName
  850. #
  851. SameTokenValuePcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))
  852. SameTokenValuePcdListCount = 0
  853. while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):
  854. Flag = False
  855. TemListItem = SameTokenValuePcdList[SameTokenValuePcdListCount]
  856. TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1]
  857. if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):
  858. for PcdItem in GlobalData.MixedPcd:
  859. if (TemListItem.TokenCName, TemListItem.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem] or \
  860. (TemListItemNext.TokenCName, TemListItemNext.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
  861. Flag = True
  862. if not Flag:
  863. EdkLogger.error(
  864. 'build',
  865. FORMAT_INVALID,
  866. "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\
  867. % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),
  868. ExtraData=None
  869. )
  870. SameTokenValuePcdListCount += 1
  871. Count += SameTokenValuePcdListCount
  872. Count += 1
  873. PcdList = list(Package.Pcds.values())
  874. PcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))
  875. Count = 0
  876. while (Count < len(PcdList) - 1) :
  877. Item = PcdList[Count]
  878. ItemNext = PcdList[Count + 1]
  879. #
  880. # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.
  881. #
  882. if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (int(Item.TokenValue, 0) != int(ItemNext.TokenValue, 0)):
  883. EdkLogger.error(
  884. 'build',
  885. FORMAT_INVALID,
  886. "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\
  887. % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),
  888. ExtraData=None
  889. )
  890. Count += 1
  891. ## Generate fds command
  892. @property
  893. def GenFdsCommand(self):
  894. return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()
  895. @property
  896. def GenFdsCommandDict(self):
  897. FdsCommandDict = {}
  898. LogLevel = EdkLogger.GetLevel()
  899. if LogLevel == EdkLogger.VERBOSE:
  900. FdsCommandDict["verbose"] = True
  901. elif LogLevel <= EdkLogger.DEBUG_9:
  902. FdsCommandDict["debug"] = LogLevel - 1
  903. elif LogLevel == EdkLogger.QUIET:
  904. FdsCommandDict["quiet"] = True
  905. if GlobalData.gEnableGenfdsMultiThread:
  906. FdsCommandDict["GenfdsMultiThread"] = True
  907. if GlobalData.gIgnoreSource:
  908. FdsCommandDict["IgnoreSources"] = True
  909. FdsCommandDict["OptionPcd"] = []
  910. for pcd in GlobalData.BuildOptionPcd:
  911. if pcd[2]:
  912. pcdname = '.'.join(pcd[0:3])
  913. else:
  914. pcdname = '.'.join(pcd[0:2])
  915. if pcd[3].startswith('{'):
  916. FdsCommandDict["OptionPcd"].append(pcdname + '=' + 'H' + '"' + pcd[3] + '"')
  917. else:
  918. FdsCommandDict["OptionPcd"].append(pcdname + '=' + pcd[3])
  919. MacroList = []
  920. # macros passed to GenFds
  921. MacroDict = {}
  922. MacroDict.update(GlobalData.gGlobalDefines)
  923. MacroDict.update(GlobalData.gCommandLineDefines)
  924. for MacroName in MacroDict:
  925. if MacroDict[MacroName] != "":
  926. MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))
  927. else:
  928. MacroList.append('"%s"' % MacroName)
  929. FdsCommandDict["macro"] = MacroList
  930. FdsCommandDict["fdf_file"] = [self.FdfFile]
  931. FdsCommandDict["build_target"] = self.BuildTarget
  932. FdsCommandDict["toolchain_tag"] = self.ToolChain
  933. FdsCommandDict["active_platform"] = str(self)
  934. FdsCommandDict["conf_directory"] = GlobalData.gConfDirectory
  935. FdsCommandDict["build_architecture_list"] = ','.join(self.ArchList)
  936. FdsCommandDict["platform_build_directory"] = self.BuildDir
  937. FdsCommandDict["fd"] = self.FdTargetList
  938. FdsCommandDict["fv"] = self.FvTargetList
  939. FdsCommandDict["cap"] = self.CapTargetList
  940. return FdsCommandDict
  941. ## Create makefile for the platform and modules in it
  942. #
  943. # @param CreateDepsMakeFile Flag indicating if the makefile for
  944. # modules will be created as well
  945. #
  946. def CreateMakeFile(self, CreateDepsMakeFile=False):
  947. if not CreateDepsMakeFile:
  948. return
  949. for Pa in self.AutoGenObjectList:
  950. Pa.CreateMakeFile(True)
  951. ## Create autogen code for platform and modules
  952. #
  953. # Since there's no autogen code for platform, this method will do nothing
  954. # if CreateModuleCodeFile is set to False.
  955. #
  956. # @param CreateDepsCodeFile Flag indicating if creating module's
  957. # autogen code file or not
  958. #
  959. def CreateCodeFile(self, CreateDepsCodeFile=False):
  960. if not CreateDepsCodeFile:
  961. return
  962. for Pa in self.AutoGenObjectList:
  963. Pa.CreateCodeFile(True)
  964. ## Create AsBuilt INF file the platform
  965. #
  966. def CreateAsBuiltInf(self):
  967. return
  968. ## AutoGen class for platform
  969. #
  970. # PlatformAutoGen class will process the original information in platform
  971. # file in order to generate makefile for platform.
  972. #
  973. class PlatformAutoGen(AutoGen):
  974. # call super().__init__ then call the worker function with different parameter count
  975. def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
  976. if not hasattr(self, "_Init"):
  977. self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch)
  978. self._Init = True
  979. #
  980. # Used to store all PCDs for both PEI and DXE phase, in order to generate
  981. # correct PCD database
  982. #
  983. _DynaPcdList_ = []
  984. _NonDynaPcdList_ = []
  985. _PlatformPcds = {}
  986. #
  987. # The priority list while override build option
  988. #
  989. PrioList = {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)
  990. "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
  991. "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE
  992. "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE
  993. "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
  994. "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE
  995. "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE
  996. "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE
  997. "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE
  998. "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE
  999. "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE
  1000. "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE
  1001. "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE
  1002. "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE
  1003. "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE
  1004. "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)
  1005. ## Initialize PlatformAutoGen
  1006. #
  1007. #
  1008. # @param Workspace WorkspaceAutoGen object
  1009. # @param PlatformFile Platform file (DSC file)
  1010. # @param Target Build target (DEBUG, RELEASE)
  1011. # @param Toolchain Name of tool chain
  1012. # @param Arch arch of the platform supports
  1013. #
  1014. def _InitWorker(self, Workspace, PlatformFile, Target, Toolchain, Arch):
  1015. EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))
  1016. GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)
  1017. self.MetaFile = PlatformFile
  1018. self.Workspace = Workspace
  1019. self.WorkspaceDir = Workspace.WorkspaceDir
  1020. self.ToolChain = Toolchain
  1021. self.BuildTarget = Target
  1022. self.Arch = Arch
  1023. self.SourceDir = PlatformFile.SubDir
  1024. self.SourceOverrideDir = None
  1025. self.FdTargetList = self.Workspace.FdTargetList
  1026. self.FvTargetList = self.Workspace.FvTargetList
  1027. # get the original module/package/platform objects
  1028. self.BuildDatabase = Workspace.BuildDatabase
  1029. self.DscBuildDataObj = Workspace.Platform
  1030. # flag indicating if the makefile/C-code file has been created or not
  1031. self.IsMakeFileCreated = False
  1032. self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
  1033. self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]
  1034. self._AsBuildInfList = []
  1035. self._AsBuildModuleList = []
  1036. self.VariableInfo = None
  1037. if GlobalData.gFdfParser is not None:
  1038. self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList
  1039. for Inf in self._AsBuildInfList:
  1040. InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)
  1041. M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
  1042. if not M.IsBinaryModule:
  1043. continue
  1044. self._AsBuildModuleList.append(InfClass)
  1045. # get library/modules for build
  1046. self.LibraryBuildDirectoryList = []
  1047. self.ModuleBuildDirectoryList = []
  1048. return True
  1049. @cached_class_function
  1050. def __repr__(self):
  1051. return "%s [%s]" % (self.MetaFile, self.Arch)
  1052. ## Create autogen code for platform and modules
  1053. #
  1054. # Since there's no autogen code for platform, this method will do nothing
  1055. # if CreateModuleCodeFile is set to False.
  1056. #
  1057. # @param CreateModuleCodeFile Flag indicating if creating module's
  1058. # autogen code file or not
  1059. #
  1060. @cached_class_function
  1061. def CreateCodeFile(self, CreateModuleCodeFile=False):
  1062. # only module has code to be created, so do nothing if CreateModuleCodeFile is False
  1063. if not CreateModuleCodeFile:
  1064. return
  1065. for Ma in self.ModuleAutoGenList:
  1066. Ma.CreateCodeFile(True)
  1067. ## Generate Fds Command
  1068. @cached_property
  1069. def GenFdsCommand(self):
  1070. return self.Workspace.GenFdsCommand
  1071. ## Create makefile for the platform and modules in it
  1072. #
  1073. # @param CreateModuleMakeFile Flag indicating if the makefile for
  1074. # modules will be created as well
  1075. #
  1076. def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):
  1077. if CreateModuleMakeFile:
  1078. for Ma in self._MaList:
  1079. key = (Ma.MetaFile.File, self.Arch)
  1080. if key in FfsCommand:
  1081. Ma.CreateMakeFile(True, FfsCommand[key])
  1082. else:
  1083. Ma.CreateMakeFile(True)
  1084. # no need to create makefile for the platform more than once
  1085. if self.IsMakeFileCreated:
  1086. return
  1087. # create library/module build dirs for platform
  1088. Makefile = GenMake.PlatformMakefile(self)
  1089. self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()
  1090. self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()
  1091. self.IsMakeFileCreated = True
  1092. @property
  1093. def AllPcdList(self):
  1094. return self.DynamicPcdList + self.NonDynamicPcdList
  1095. ## Deal with Shared FixedAtBuild Pcds
  1096. #
  1097. def CollectFixedAtBuildPcds(self):
  1098. for LibAuto in self.LibraryAutoGenList:
  1099. FixedAtBuildPcds = {}
  1100. ShareFixedAtBuildPcdsSameValue = {}
  1101. for Module in LibAuto.ReferenceModules:
  1102. for Pcd in set(Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds):
  1103. DefaultValue = Pcd.DefaultValue
  1104. # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib
  1105. if Pcd in Module.LibraryPcdList:
  1106. Index = Module.LibraryPcdList.index(Pcd)
  1107. DefaultValue = Module.LibraryPcdList[Index].DefaultValue
  1108. key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
  1109. if key not in FixedAtBuildPcds:
  1110. ShareFixedAtBuildPcdsSameValue[key] = True
  1111. FixedAtBuildPcds[key] = DefaultValue
  1112. else:
  1113. if FixedAtBuildPcds[key] != DefaultValue:
  1114. ShareFixedAtBuildPcdsSameValue[key] = False
  1115. for Pcd in LibAuto.FixedAtBuildPcds:
  1116. key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
  1117. if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:
  1118. continue
  1119. else:
  1120. DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)]
  1121. if DscPcd.Type != TAB_PCDS_FIXED_AT_BUILD:
  1122. continue
  1123. if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:
  1124. LibAuto.ConstPcd[key] = FixedAtBuildPcds[key]
  1125. def CollectVariables(self, DynamicPcdSet):
  1126. VpdRegionSize = 0
  1127. VpdRegionBase = 0
  1128. if self.Workspace.FdfFile:
  1129. FdDict = self.Workspace.FdfProfile.FdDict[GlobalData.gFdfParser.CurrentFdName]
  1130. for FdRegion in FdDict.RegionList:
  1131. for item in FdRegion.RegionDataList:
  1132. if self.Platform.VpdToolGuid.strip() and self.Platform.VpdToolGuid in item:
  1133. VpdRegionSize = FdRegion.Size
  1134. VpdRegionBase = FdRegion.Offset
  1135. break
  1136. VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(), self.DscBuildDataObj.SkuIds)
  1137. VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)
  1138. VariableInfo.SetVpdRegionOffset(VpdRegionBase)
  1139. Index = 0
  1140. for Pcd in DynamicPcdSet:
  1141. pcdname = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
  1142. for SkuName in Pcd.SkuInfoList:
  1143. Sku = Pcd.SkuInfoList[SkuName]
  1144. SkuId = Sku.SkuId
  1145. if SkuId is None or SkuId == '':
  1146. continue
  1147. if len(Sku.VariableName) > 0:
  1148. if Sku.VariableAttribute and 'NV' not in Sku.VariableAttribute:
  1149. continue
  1150. VariableGuidStructure = Sku.VariableGuidValue
  1151. VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)
  1152. for StorageName in Sku.DefaultStoreDict:
  1153. VariableInfo.append_variable(var_info(Index, pcdname, StorageName, SkuName, StringToArray(Sku.VariableName), VariableGuid, Sku.VariableOffset, Sku.VariableAttribute, Sku.HiiDefaultValue, Sku.DefaultStoreDict[StorageName] if Pcd.DatumType in TAB_PCD_NUMERIC_TYPES else StringToArray(Sku.DefaultStoreDict[StorageName]), Pcd.DatumType, Pcd.CustomAttribute['DscPosition'], Pcd.CustomAttribute.get('IsStru',False)))
  1154. Index += 1
  1155. return VariableInfo
  1156. def UpdateNVStoreMaxSize(self, OrgVpdFile):
  1157. if self.VariableInfo:
  1158. VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)
  1159. PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]
  1160. if PcdNvStoreDfBuffer:
  1161. if os.path.exists(VpdMapFilePath):
  1162. OrgVpdFile.Read(VpdMapFilePath)
  1163. PcdItems = OrgVpdFile.GetOffset(PcdNvStoreDfBuffer[0])
  1164. NvStoreOffset = list(PcdItems.values())[0].strip() if PcdItems else '0'
  1165. else:
  1166. EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
  1167. NvStoreOffset = int(NvStoreOffset, 16) if NvStoreOffset.upper().startswith("0X") else int(NvStoreOffset)
  1168. default_skuobj = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)
  1169. maxsize = self.VariableInfo.VpdRegionSize - NvStoreOffset if self.VariableInfo.VpdRegionSize else len(default_skuobj.DefaultValue.split(","))
  1170. var_data = self.VariableInfo.PatchNVStoreDefaultMaxSize(maxsize)
  1171. if var_data and default_skuobj:
  1172. default_skuobj.DefaultValue = var_data
  1173. PcdNvStoreDfBuffer[0].DefaultValue = var_data
  1174. PcdNvStoreDfBuffer[0].SkuInfoList.clear()
  1175. PcdNvStoreDfBuffer[0].SkuInfoList[TAB_DEFAULT] = default_skuobj
  1176. PcdNvStoreDfBuffer[0].MaxDatumSize = str(len(default_skuobj.DefaultValue.split(",")))
  1177. return OrgVpdFile
  1178. ## Collect dynamic PCDs
  1179. #
  1180. # Gather dynamic PCDs list from each module and their settings from platform
  1181. # This interface should be invoked explicitly when platform action is created.
  1182. #
  1183. def CollectPlatformDynamicPcds(self):
  1184. for key in self.Platform.Pcds:
  1185. for SinglePcd in GlobalData.MixedPcd:
  1186. if (self.Platform.Pcds[key].TokenCName, self.Platform.Pcds[key].TokenSpaceGuidCName) == SinglePcd:
  1187. for item in GlobalData.MixedPcd[SinglePcd]:
  1188. Pcd_Type = item[0].split('_')[-1]
  1189. if (Pcd_Type == self.Platform.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and self.Platform.Pcds[key].Type in PCD_DYNAMIC_EX_TYPE_SET) or \
  1190. (Pcd_Type == TAB_PCDS_DYNAMIC and self.Platform.Pcds[key].Type in PCD_DYNAMIC_TYPE_SET):
  1191. Value = self.Platform.Pcds[key]
  1192. Value.TokenCName = self.Platform.Pcds[key].TokenCName + '_' + Pcd_Type
  1193. if len(key) == 2:
  1194. newkey = (Value.TokenCName, key[1])
  1195. elif len(key) == 3:
  1196. newkey = (Value.TokenCName, key[1], key[2])
  1197. del self.Platform.Pcds[key]
  1198. self.Platform.Pcds[newkey] = Value
  1199. break
  1200. break
  1201. # for gathering error information
  1202. NoDatumTypePcdList = set()
  1203. FdfModuleList = []
  1204. for InfName in self._AsBuildInfList:
  1205. InfName = mws.join(self.WorkspaceDir, InfName)
  1206. FdfModuleList.append(os.path.normpath(InfName))
  1207. for M in self._MaList:
  1208. # F is the Module for which M is the module autogen
  1209. for PcdFromModule in M.ModulePcdList + M.LibraryPcdList:
  1210. # make sure that the "VOID*" kind of datum has MaxDatumSize set
  1211. if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:
  1212. NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, M.MetaFile))
  1213. # Check the PCD from Binary INF or Source INF
  1214. if M.IsBinaryModule == True:
  1215. PcdFromModule.IsFromBinaryInf = True
  1216. # Check the PCD from DSC or not
  1217. PcdFromModule.IsFromDsc = (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds
  1218. if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET or PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
  1219. if M.MetaFile.Path not in FdfModuleList:
  1220. # If one of the Source built modules listed in the DSC is not listed
  1221. # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic
  1222. # access method (it is only listed in the DEC file that declares the
  1223. # PCD as PcdsDynamic), then build tool will report warning message
  1224. # notify the PI that they are attempting to build a module that must
  1225. # be included in a flash image in order to be functional. These Dynamic
  1226. # PCD will not be added into the Database unless it is used by other
  1227. # modules that are included in the FDF file.
  1228. if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET and \
  1229. PcdFromModule.IsFromBinaryInf == False:
  1230. # Print warning message to let the developer make a determine.
  1231. continue
  1232. # If one of the Source built modules listed in the DSC is not listed in
  1233. # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx
  1234. # access method (it is only listed in the DEC file that declares the
  1235. # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the
  1236. # PCD to the Platform's PCD Database.
  1237. if PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
  1238. continue
  1239. #
  1240. # If a dynamic PCD used by a PEM module/PEI module & DXE module,
  1241. # it should be stored in Pcd PEI database, If a dynamic only
  1242. # used by DXE module, it should be stored in DXE PCD database.
  1243. # The default Phase is DXE
  1244. #
  1245. if M.ModuleType in SUP_MODULE_SET_PEI:
  1246. PcdFromModule.Phase = "PEI"
  1247. if PcdFromModule not in self._DynaPcdList_:
  1248. self._DynaPcdList_.append(PcdFromModule)
  1249. elif PcdFromModule.Phase == 'PEI':
  1250. # overwrite any the same PCD existing, if Phase is PEI
  1251. Index = self._DynaPcdList_.index(PcdFromModule)
  1252. self._DynaPcdList_[Index] = PcdFromModule
  1253. elif PcdFromModule not in self._NonDynaPcdList_:
  1254. self._NonDynaPcdList_.append(PcdFromModule)
  1255. elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:
  1256. Index = self._NonDynaPcdList_.index(PcdFromModule)
  1257. if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:
  1258. #The PCD from Binary INF will override the same one from source INF
  1259. self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])
  1260. PcdFromModule.Pending = False
  1261. self._NonDynaPcdList_.append (PcdFromModule)
  1262. DscModuleSet = {os.path.normpath(ModuleInf.Path) for ModuleInf in self.Platform.Modules}
  1263. # add the PCD from modules that listed in FDF but not in DSC to Database
  1264. for InfName in FdfModuleList:
  1265. if InfName not in DscModuleSet:
  1266. InfClass = PathClass(InfName)
  1267. M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]
  1268. # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)
  1269. # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.
  1270. # For binary module, if in current arch, we need to list the PCDs into database.
  1271. if not M.IsBinaryModule:
  1272. continue
  1273. # Override the module PCD setting by platform setting
  1274. ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)
  1275. for PcdFromModule in ModulePcdList:
  1276. PcdFromModule.IsFromBinaryInf = True
  1277. PcdFromModule.IsFromDsc = False
  1278. # Only allow the DynamicEx and Patchable PCD in AsBuild INF
  1279. if PcdFromModule.Type not in PCD_DYNAMIC_EX_TYPE_SET and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:
  1280. EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
  1281. File=self.MetaFile,
  1282. ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"
  1283. % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))
  1284. # make sure that the "VOID*" kind of datum has MaxDatumSize set
  1285. if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:
  1286. NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))
  1287. if M.ModuleType in SUP_MODULE_SET_PEI:
  1288. PcdFromModule.Phase = "PEI"
  1289. if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
  1290. self._DynaPcdList_.append(PcdFromModule)
  1291. elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:
  1292. self._NonDynaPcdList_.append(PcdFromModule)
  1293. if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:
  1294. # Overwrite the phase of any the same PCD existing, if Phase is PEI.
  1295. # It is to solve the case that a dynamic PCD used by a PEM module/PEI
  1296. # module & DXE module at a same time.
  1297. # Overwrite the type of the PCDs in source INF by the type of AsBuild
  1298. # INF file as DynamicEx.
  1299. Index = self._DynaPcdList_.index(PcdFromModule)
  1300. self._DynaPcdList_[Index].Phase = PcdFromModule.Phase
  1301. self._DynaPcdList_[Index].Type = PcdFromModule.Type
  1302. for PcdFromModule in self._NonDynaPcdList_:
  1303. # If a PCD is not listed in the DSC file, but binary INF files used by
  1304. # this platform all (that use this PCD) list the PCD in a [PatchPcds]
  1305. # section, AND all source INF files used by this platform the build
  1306. # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]
  1307. # section, then the tools must NOT add the PCD to the Platform's PCD
  1308. # Database; the build must assign the access method for this PCD as
  1309. # PcdsPatchableInModule.
  1310. if PcdFromModule not in self._DynaPcdList_:
  1311. continue
  1312. Index = self._DynaPcdList_.index(PcdFromModule)
  1313. if PcdFromModule.IsFromDsc == False and \
  1314. PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \
  1315. PcdFromModule.IsFromBinaryInf == True and \
  1316. self._DynaPcdList_[Index].IsFromBinaryInf == False:
  1317. Index = self._DynaPcdList_.index(PcdFromModule)
  1318. self._DynaPcdList_.remove (self._DynaPcdList_[Index])
  1319. # print out error information and break the build, if error found
  1320. if len(NoDatumTypePcdList) > 0:
  1321. NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)
  1322. EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",
  1323. File=self.MetaFile,
  1324. ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"
  1325. % NoDatumTypePcdListString)
  1326. self._NonDynamicPcdList = self._NonDynaPcdList_
  1327. self._DynamicPcdList = self._DynaPcdList_
  1328. #
  1329. # Sort dynamic PCD list to:
  1330. # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should
  1331. # try to be put header of dynamicd List
  1332. # 2) If PCD is HII type, the PCD item should be put after unicode type PCD
  1333. #
  1334. # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.
  1335. #
  1336. UnicodePcdArray = set()
  1337. HiiPcdArray = set()
  1338. OtherPcdArray = set()
  1339. VpdPcdDict = {}
  1340. VpdFile = VpdInfoFile.VpdInfoFile()
  1341. NeedProcessVpdMapFile = False
  1342. for pcd in self.Platform.Pcds:
  1343. if pcd not in self._PlatformPcds:
  1344. self._PlatformPcds[pcd] = self.Platform.Pcds[pcd]
  1345. for item in self._PlatformPcds:
  1346. if self._PlatformPcds[item].DatumType and self._PlatformPcds[item].DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
  1347. self._PlatformPcds[item].DatumType = TAB_VOID
  1348. if (self.Workspace.ArchList[-1] == self.Arch):
  1349. for Pcd in self._DynamicPcdList:
  1350. # just pick the a value to determine whether is unicode string type
  1351. Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)
  1352. Sku.VpdOffset = Sku.VpdOffset.strip()
  1353. if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
  1354. Pcd.DatumType = TAB_VOID
  1355. # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
  1356. # if found HII type PCD then insert to right of UnicodeIndex
  1357. if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
  1358. VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd
  1359. #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer
  1360. PcdNvStoreDfBuffer = VpdPcdDict.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))
  1361. if PcdNvStoreDfBuffer:
  1362. self.VariableInfo = self.CollectVariables(self._DynamicPcdList)
  1363. vardump = self.VariableInfo.dump()
  1364. if vardump:
  1365. #
  1366. #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,
  1367. #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).
  1368. #typedef UINT16 SIZE_INFO;
  1369. #//SIZE_INFO SizeTable[];
  1370. if len(vardump.split(",")) > 0xffff:
  1371. EdkLogger.error("build", RESOURCE_OVERFLOW, 'The current length of PCD %s value is %d, it exceeds to the max size of String PCD.' %(".".join([PcdNvStoreDfBuffer.TokenSpaceGuidCName,PcdNvStoreDfBuffer.TokenCName]) ,len(vardump.split(","))))
  1372. PcdNvStoreDfBuffer.DefaultValue = vardump
  1373. for skuname in PcdNvStoreDfBuffer.SkuInfoList:
  1374. PcdNvStoreDfBuffer.SkuInfoList[skuname].DefaultValue = vardump
  1375. PcdNvStoreDfBuffer.MaxDatumSize = str(len(vardump.split(",")))
  1376. else:
  1377. #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd
  1378. if [Pcd for Pcd in self._DynamicPcdList if Pcd.UserDefinedDefaultStoresFlag]:
  1379. EdkLogger.warn("build", "PcdNvStoreDefaultValueBuffer should be defined as PcdsDynamicExVpd in dsc file since the DefaultStores is enabled for this platform.\n%s" %self.Platform.MetaFile.Path)
  1380. PlatformPcds = sorted(self._PlatformPcds.keys())
  1381. #
  1382. # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.
  1383. #
  1384. VpdSkuMap = {}
  1385. for PcdKey in PlatformPcds:
  1386. Pcd = self._PlatformPcds[PcdKey]
  1387. if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \
  1388. PcdKey in VpdPcdDict:
  1389. Pcd = VpdPcdDict[PcdKey]
  1390. SkuValueMap = {}
  1391. DefaultSku = Pcd.SkuInfoList.get(TAB_DEFAULT)
  1392. if DefaultSku:
  1393. PcdValue = DefaultSku.DefaultValue
  1394. if PcdValue not in SkuValueMap:
  1395. SkuValueMap[PcdValue] = []
  1396. VpdFile.Add(Pcd, TAB_DEFAULT, DefaultSku.VpdOffset)
  1397. SkuValueMap[PcdValue].append(DefaultSku)
  1398. for (SkuName, Sku) in Pcd.SkuInfoList.items():
  1399. Sku.VpdOffset = Sku.VpdOffset.strip()
  1400. PcdValue = Sku.DefaultValue
  1401. if PcdValue == "":
  1402. PcdValue = Pcd.DefaultValue
  1403. if Sku.VpdOffset != TAB_STAR:
  1404. if PcdValue.startswith("{"):
  1405. Alignment = 8
  1406. elif PcdValue.startswith("L"):
  1407. Alignment = 2
  1408. else:
  1409. Alignment = 1
  1410. try:
  1411. VpdOffset = int(Sku.VpdOffset)
  1412. except:
  1413. try:
  1414. VpdOffset = int(Sku.VpdOffset, 16)
  1415. except:
  1416. EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
  1417. if VpdOffset % Alignment != 0:
  1418. if PcdValue.startswith("{"):
  1419. EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName), File=self.MetaFile)
  1420. else:
  1421. EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Alignment))
  1422. if PcdValue not in SkuValueMap:
  1423. SkuValueMap[PcdValue] = []
  1424. VpdFile.Add(Pcd, SkuName, Sku.VpdOffset)
  1425. SkuValueMap[PcdValue].append(Sku)
  1426. # if the offset of a VPD is *, then it need to be fixed up by third party tool.
  1427. if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:
  1428. NeedProcessVpdMapFile = True
  1429. if self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == '':
  1430. EdkLogger.error("Build", FILE_NOT_FOUND, \
  1431. "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
  1432. VpdSkuMap[PcdKey] = SkuValueMap
  1433. #
  1434. # Fix the PCDs define in VPD PCD section that never referenced by module.
  1435. # An example is PCD for signature usage.
  1436. #
  1437. for DscPcd in PlatformPcds:
  1438. DscPcdEntry = self._PlatformPcds[DscPcd]
  1439. if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:
  1440. if not (self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == ''):
  1441. FoundFlag = False
  1442. for VpdPcd in VpdFile._VpdArray:
  1443. # This PCD has been referenced by module
  1444. if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
  1445. (VpdPcd.TokenCName == DscPcdEntry.TokenCName):
  1446. FoundFlag = True
  1447. # Not found, it should be signature
  1448. if not FoundFlag :
  1449. # just pick the a value to determine whether is unicode string type
  1450. SkuValueMap = {}
  1451. SkuObjList = list(DscPcdEntry.SkuInfoList.items())
  1452. DefaultSku = DscPcdEntry.SkuInfoList.get(TAB_DEFAULT)
  1453. if DefaultSku:
  1454. defaultindex = SkuObjList.index((TAB_DEFAULT, DefaultSku))
  1455. SkuObjList[0], SkuObjList[defaultindex] = SkuObjList[defaultindex], SkuObjList[0]
  1456. for (SkuName, Sku) in SkuObjList:
  1457. Sku.VpdOffset = Sku.VpdOffset.strip()
  1458. # Need to iterate DEC pcd information to get the value & datumtype
  1459. for eachDec in self.PackageList:
  1460. for DecPcd in eachDec.Pcds:
  1461. DecPcdEntry = eachDec.Pcds[DecPcd]
  1462. if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \
  1463. (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):
  1464. # Print warning message to let the developer make a determine.
  1465. EdkLogger.warn("build", "Unreferenced vpd pcd used!",
  1466. File=self.MetaFile, \
  1467. ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \
  1468. %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))
  1469. DscPcdEntry.DatumType = DecPcdEntry.DatumType
  1470. DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue
  1471. DscPcdEntry.TokenValue = DecPcdEntry.TokenValue
  1472. DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]
  1473. # Only fix the value while no value provided in DSC file.
  1474. if not Sku.DefaultValue:
  1475. DscPcdEntry.SkuInfoList[list(DscPcdEntry.SkuInfoList.keys())[0]].DefaultValue = DecPcdEntry.DefaultValue
  1476. if DscPcdEntry not in self._DynamicPcdList:
  1477. self._DynamicPcdList.append(DscPcdEntry)
  1478. Sku.VpdOffset = Sku.VpdOffset.strip()
  1479. PcdValue = Sku.DefaultValue
  1480. if PcdValue == "":
  1481. PcdValue = DscPcdEntry.DefaultValue
  1482. if Sku.VpdOffset != TAB_STAR:
  1483. if PcdValue.startswith("{"):
  1484. Alignment = 8
  1485. elif PcdValue.startswith("L"):
  1486. Alignment = 2
  1487. else:
  1488. Alignment = 1
  1489. try:
  1490. VpdOffset = int(Sku.VpdOffset)
  1491. except:
  1492. try:
  1493. VpdOffset = int(Sku.VpdOffset, 16)
  1494. except:
  1495. EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName))
  1496. if VpdOffset % Alignment != 0:
  1497. if PcdValue.startswith("{"):
  1498. EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName), File=self.MetaFile)
  1499. else:
  1500. EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, Alignment))
  1501. if PcdValue not in SkuValueMap:
  1502. SkuValueMap[PcdValue] = []
  1503. VpdFile.Add(DscPcdEntry, SkuName, Sku.VpdOffset)
  1504. SkuValueMap[PcdValue].append(Sku)
  1505. if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:
  1506. NeedProcessVpdMapFile = True
  1507. if DscPcdEntry.DatumType == TAB_VOID and PcdValue.startswith("L"):
  1508. UnicodePcdArray.add(DscPcdEntry)
  1509. elif len(Sku.VariableName) > 0:
  1510. HiiPcdArray.add(DscPcdEntry)
  1511. else:
  1512. OtherPcdArray.add(DscPcdEntry)
  1513. # if the offset of a VPD is *, then it need to be fixed up by third party tool.
  1514. VpdSkuMap[DscPcd] = SkuValueMap
  1515. if (self.Platform.FlashDefinition is None or self.Platform.FlashDefinition == '') and \
  1516. VpdFile.GetCount() != 0:
  1517. EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
  1518. "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))
  1519. if VpdFile.GetCount() != 0:
  1520. self.FixVpdOffset(VpdFile)
  1521. self.FixVpdOffset(self.UpdateNVStoreMaxSize(VpdFile))
  1522. PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]
  1523. if PcdNvStoreDfBuffer:
  1524. PcdName,PcdGuid = PcdNvStoreDfBuffer[0].TokenCName, PcdNvStoreDfBuffer[0].TokenSpaceGuidCName
  1525. if (PcdName,PcdGuid) in VpdSkuMap:
  1526. DefaultSku = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)
  1527. VpdSkuMap[(PcdName,PcdGuid)] = {DefaultSku.DefaultValue:[DefaultSku]}
  1528. # Process VPD map file generated by third party BPDG tool
  1529. if NeedProcessVpdMapFile:
  1530. VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)
  1531. if os.path.exists(VpdMapFilePath):
  1532. VpdFile.Read(VpdMapFilePath)
  1533. # Fixup TAB_STAR offset
  1534. for pcd in VpdSkuMap:
  1535. vpdinfo = VpdFile.GetVpdInfo(pcd)
  1536. if vpdinfo is None:
  1537. # just pick the a value to determine whether is unicode string type
  1538. continue
  1539. for pcdvalue in VpdSkuMap[pcd]:
  1540. for sku in VpdSkuMap[pcd][pcdvalue]:
  1541. for item in vpdinfo:
  1542. if item[2] == pcdvalue:
  1543. sku.VpdOffset = item[1]
  1544. else:
  1545. EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)
  1546. # Delete the DynamicPcdList At the last time enter into this function
  1547. for Pcd in self._DynamicPcdList:
  1548. # just pick the a value to determine whether is unicode string type
  1549. Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)
  1550. Sku.VpdOffset = Sku.VpdOffset.strip()
  1551. if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
  1552. Pcd.DatumType = TAB_VOID
  1553. PcdValue = Sku.DefaultValue
  1554. if Pcd.DatumType == TAB_VOID and PcdValue.startswith("L"):
  1555. # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex
  1556. UnicodePcdArray.add(Pcd)
  1557. elif len(Sku.VariableName) > 0:
  1558. # if found HII type PCD then insert to right of UnicodeIndex
  1559. HiiPcdArray.add(Pcd)
  1560. else:
  1561. OtherPcdArray.add(Pcd)
  1562. del self._DynamicPcdList[:]
  1563. self._DynamicPcdList.extend(list(UnicodePcdArray))
  1564. self._DynamicPcdList.extend(list(HiiPcdArray))
  1565. self._DynamicPcdList.extend(list(OtherPcdArray))
  1566. allskuset = [(SkuName, Sku.SkuId) for pcd in self._DynamicPcdList for (SkuName, Sku) in pcd.SkuInfoList.items()]
  1567. for pcd in self._DynamicPcdList:
  1568. if len(pcd.SkuInfoList) == 1:
  1569. for (SkuName, SkuId) in allskuset:
  1570. if isinstance(SkuId, str) and eval(SkuId) == 0 or SkuId == 0:
  1571. continue
  1572. pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList[TAB_DEFAULT])
  1573. pcd.SkuInfoList[SkuName].SkuId = SkuId
  1574. pcd.SkuInfoList[SkuName].SkuIdName = SkuName
  1575. def FixVpdOffset(self, VpdFile ):
  1576. FvPath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY)
  1577. if not os.path.exists(FvPath):
  1578. try:
  1579. os.makedirs(FvPath)
  1580. except:
  1581. EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)
  1582. VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)
  1583. if VpdFile.Write(VpdFilePath):
  1584. # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.
  1585. BPDGToolName = None
  1586. for ToolDef in self.ToolDefinition.values():
  1587. if TAB_GUID in ToolDef and ToolDef[TAB_GUID] == self.Platform.VpdToolGuid:
  1588. if "PATH" not in ToolDef:
  1589. EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)
  1590. BPDGToolName = ToolDef["PATH"]
  1591. break
  1592. # Call third party GUID BPDG tool.
  1593. if BPDGToolName is not None:
  1594. VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)
  1595. else:
  1596. EdkLogger.error("Build", FILE_NOT_FOUND, "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")
  1597. ## Return the platform build data object
  1598. @cached_property
  1599. def Platform(self):
  1600. return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
  1601. ## Return platform name
  1602. @cached_property
  1603. def Name(self):
  1604. return self.Platform.PlatformName
  1605. ## Return the meta file GUID
  1606. @cached_property
  1607. def Guid(self):
  1608. return self.Platform.Guid
  1609. ## Return the platform version
  1610. @cached_property
  1611. def Version(self):
  1612. return self.Platform.Version
  1613. ## Return the FDF file name
  1614. @cached_property
  1615. def FdfFile(self):
  1616. if self.Workspace.FdfFile:
  1617. RetVal= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)
  1618. else:
  1619. RetVal = ''
  1620. return RetVal
  1621. ## Return the build output directory platform specifies
  1622. @cached_property
  1623. def OutputDir(self):
  1624. return self.Platform.OutputDirectory
  1625. ## Return the directory to store all intermediate and final files built
  1626. @cached_property
  1627. def BuildDir(self):
  1628. if os.path.isabs(self.OutputDir):
  1629. GlobalData.gBuildDirectory = RetVal = path.join(
  1630. path.abspath(self.OutputDir),
  1631. self.BuildTarget + "_" + self.ToolChain,
  1632. )
  1633. else:
  1634. GlobalData.gBuildDirectory = RetVal = path.join(
  1635. self.WorkspaceDir,
  1636. self.OutputDir,
  1637. self.BuildTarget + "_" + self.ToolChain,
  1638. )
  1639. return RetVal
  1640. ## Return directory of platform makefile
  1641. #
  1642. # @retval string Makefile directory
  1643. #
  1644. @cached_property
  1645. def MakeFileDir(self):
  1646. return path.join(self.BuildDir, self.Arch)
  1647. ## Return build command string
  1648. #
  1649. # @retval string Build command string
  1650. #
  1651. @cached_property
  1652. def BuildCommand(self):
  1653. RetVal = []
  1654. if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
  1655. RetVal += _SplitOption(self.ToolDefinition["MAKE"]["PATH"])
  1656. if "FLAGS" in self.ToolDefinition["MAKE"]:
  1657. NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
  1658. if NewOption != '':
  1659. RetVal += _SplitOption(NewOption)
  1660. if "MAKE" in self.EdkIIBuildOption:
  1661. if "FLAGS" in self.EdkIIBuildOption["MAKE"]:
  1662. Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]
  1663. if Flags.startswith('='):
  1664. RetVal = [RetVal[0]] + [Flags[1:]]
  1665. else:
  1666. RetVal.append(Flags)
  1667. return RetVal
  1668. ## Get tool chain definition
  1669. #
  1670. # Get each tool definition for given tool chain from tools_def.txt and platform
  1671. #
  1672. @cached_property
  1673. def ToolDefinition(self):
  1674. ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary
  1675. if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:
  1676. EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",
  1677. ExtraData="[%s]" % self.MetaFile)
  1678. RetVal = {}
  1679. DllPathList = set()
  1680. for Def in ToolDefinition:
  1681. Target, Tag, Arch, Tool, Attr = Def.split("_")
  1682. if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
  1683. continue
  1684. Value = ToolDefinition[Def]
  1685. # don't record the DLL
  1686. if Attr == "DLL":
  1687. DllPathList.add(Value)
  1688. continue
  1689. if Tool not in RetVal:
  1690. RetVal[Tool] = {}
  1691. RetVal[Tool][Attr] = Value
  1692. ToolsDef = ''
  1693. if GlobalData.gOptions.SilentMode and "MAKE" in RetVal:
  1694. if "FLAGS" not in RetVal["MAKE"]:
  1695. RetVal["MAKE"]["FLAGS"] = ""
  1696. RetVal["MAKE"]["FLAGS"] += " -s"
  1697. MakeFlags = ''
  1698. for Tool in RetVal:
  1699. for Attr in RetVal[Tool]:
  1700. Value = RetVal[Tool][Attr]
  1701. if Tool in self._BuildOptionWithToolDef(RetVal) and Attr in self._BuildOptionWithToolDef(RetVal)[Tool]:
  1702. # check if override is indicated
  1703. if self._BuildOptionWithToolDef(RetVal)[Tool][Attr].startswith('='):
  1704. Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr][1:]
  1705. else:
  1706. if Attr != 'PATH':
  1707. Value += " " + self._BuildOptionWithToolDef(RetVal)[Tool][Attr]
  1708. else:
  1709. Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr]
  1710. if Attr == "PATH":
  1711. # Don't put MAKE definition in the file
  1712. if Tool != "MAKE":
  1713. ToolsDef += "%s = %s\n" % (Tool, Value)
  1714. elif Attr != "DLL":
  1715. # Don't put MAKE definition in the file
  1716. if Tool == "MAKE":
  1717. if Attr == "FLAGS":
  1718. MakeFlags = Value
  1719. else:
  1720. ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
  1721. ToolsDef += "\n"
  1722. SaveFileOnChange(self.ToolDefinitionFile, ToolsDef, False)
  1723. for DllPath in DllPathList:
  1724. os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]
  1725. os.environ["MAKE_FLAGS"] = MakeFlags
  1726. return RetVal
  1727. ## Return the paths of tools
  1728. @cached_property
  1729. def ToolDefinitionFile(self):
  1730. return os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)
  1731. ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.
  1732. @cached_property
  1733. def ToolChainFamily(self):
  1734. ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
  1735. if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \
  1736. or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \
  1737. or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:
  1738. EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
  1739. % self.ToolChain)
  1740. RetVal = TAB_COMPILER_MSFT
  1741. else:
  1742. RetVal = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]
  1743. return RetVal
  1744. @cached_property
  1745. def BuildRuleFamily(self):
  1746. ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase
  1747. if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \
  1748. or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \
  1749. or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:
  1750. EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \
  1751. % self.ToolChain)
  1752. return TAB_COMPILER_MSFT
  1753. return ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]
  1754. ## Return the build options specific for all modules in this platform
  1755. @cached_property
  1756. def BuildOption(self):
  1757. return self._ExpandBuildOption(self.Platform.BuildOptions)
  1758. def _BuildOptionWithToolDef(self, ToolDef):
  1759. return self._ExpandBuildOption(self.Platform.BuildOptions, ToolDef=ToolDef)
  1760. ## Return the build options specific for EDK modules in this platform
  1761. @cached_property
  1762. def EdkBuildOption(self):
  1763. return self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)
  1764. ## Return the build options specific for EDKII modules in this platform
  1765. @cached_property
  1766. def EdkIIBuildOption(self):
  1767. return self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)
  1768. ## Parse build_rule.txt in Conf Directory.
  1769. #
  1770. # @retval BuildRule object
  1771. #
  1772. @cached_property
  1773. def BuildRule(self):
  1774. BuildRuleFile = None
  1775. if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:
  1776. BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]
  1777. if not BuildRuleFile:
  1778. BuildRuleFile = gDefaultBuildRuleFile
  1779. RetVal = BuildRule(BuildRuleFile)
  1780. if RetVal._FileVersion == "":
  1781. RetVal._FileVersion = AutoGenReqBuildRuleVerNum
  1782. else:
  1783. if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :
  1784. # If Build Rule's version is less than the version number required by the tools, halting the build.
  1785. EdkLogger.error("build", AUTOGEN_ERROR,
  1786. ExtraData="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\
  1787. % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))
  1788. return RetVal
  1789. ## Summarize the packages used by modules in this platform
  1790. @cached_property
  1791. def PackageList(self):
  1792. RetVal = set()
  1793. for La in self.LibraryAutoGenList:
  1794. RetVal.update(La.DependentPackageList)
  1795. for Ma in self.ModuleAutoGenList:
  1796. RetVal.update(Ma.DependentPackageList)
  1797. #Collect package set information from INF of FDF
  1798. for ModuleFile in self._AsBuildModuleList:
  1799. if ModuleFile in self.Platform.Modules:
  1800. continue
  1801. ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]
  1802. RetVal.update(ModuleData.Packages)
  1803. return list(RetVal)
  1804. @cached_property
  1805. def NonDynamicPcdDict(self):
  1806. return {(Pcd.TokenCName, Pcd.TokenSpaceGuidCName):Pcd for Pcd in self.NonDynamicPcdList}
  1807. ## Get list of non-dynamic PCDs
  1808. @property
  1809. def NonDynamicPcdList(self):
  1810. if not self._NonDynamicPcdList:
  1811. self.CollectPlatformDynamicPcds()
  1812. return self._NonDynamicPcdList
  1813. ## Get list of dynamic PCDs
  1814. @property
  1815. def DynamicPcdList(self):
  1816. if not self._DynamicPcdList:
  1817. self.CollectPlatformDynamicPcds()
  1818. return self._DynamicPcdList
  1819. ## Generate Token Number for all PCD
  1820. @cached_property
  1821. def PcdTokenNumber(self):
  1822. RetVal = OrderedDict()
  1823. TokenNumber = 1
  1824. #
  1825. # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.
  1826. # Such as:
  1827. #
  1828. # Dynamic PCD:
  1829. # TokenNumber 0 ~ 10
  1830. # DynamicEx PCD:
  1831. # TokeNumber 11 ~ 20
  1832. #
  1833. for Pcd in self.DynamicPcdList:
  1834. if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:
  1835. EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
  1836. RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
  1837. TokenNumber += 1
  1838. for Pcd in self.DynamicPcdList:
  1839. if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
  1840. EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
  1841. RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
  1842. TokenNumber += 1
  1843. for Pcd in self.DynamicPcdList:
  1844. if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:
  1845. EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
  1846. RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
  1847. TokenNumber += 1
  1848. for Pcd in self.DynamicPcdList:
  1849. if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
  1850. EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))
  1851. RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
  1852. TokenNumber += 1
  1853. for Pcd in self.NonDynamicPcdList:
  1854. RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
  1855. TokenNumber += 1
  1856. return RetVal
  1857. @cached_property
  1858. def _MaList(self):
  1859. for ModuleFile in self.Platform.Modules:
  1860. Ma = ModuleAutoGen(
  1861. self.Workspace,
  1862. ModuleFile,
  1863. self.BuildTarget,
  1864. self.ToolChain,
  1865. self.Arch,
  1866. self.MetaFile
  1867. )
  1868. self.Platform.Modules[ModuleFile].M = Ma
  1869. return [x.M for x in self.Platform.Modules.values()]
  1870. ## Summarize ModuleAutoGen objects of all modules to be built for this platform
  1871. @cached_property
  1872. def ModuleAutoGenList(self):
  1873. RetVal = []
  1874. for Ma in self._MaList:
  1875. if Ma not in RetVal:
  1876. RetVal.append(Ma)
  1877. return RetVal
  1878. ## Summarize ModuleAutoGen objects of all libraries to be built for this platform
  1879. @cached_property
  1880. def LibraryAutoGenList(self):
  1881. RetVal = []
  1882. for Ma in self._MaList:
  1883. for La in Ma.LibraryAutoGenList:
  1884. if La not in RetVal:
  1885. RetVal.append(La)
  1886. if Ma not in La.ReferenceModules:
  1887. La.ReferenceModules.append(Ma)
  1888. return RetVal
  1889. ## Test if a module is supported by the platform
  1890. #
  1891. # An error will be raised directly if the module or its arch is not supported
  1892. # by the platform or current configuration
  1893. #
  1894. def ValidModule(self, Module):
  1895. return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \
  1896. or Module in self._AsBuildModuleList
  1897. ## Resolve the library classes in a module to library instances
  1898. #
  1899. # This method will not only resolve library classes but also sort the library
  1900. # instances according to the dependency-ship.
  1901. #
  1902. # @param Module The module from which the library classes will be resolved
  1903. #
  1904. # @retval library_list List of library instances sorted
  1905. #
  1906. def ApplyLibraryInstance(self, Module):
  1907. # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly
  1908. if str(Module) not in self.Platform.Modules:
  1909. return []
  1910. return GetModuleLibInstances(Module,
  1911. self.Platform,
  1912. self.BuildDatabase,
  1913. self.Arch,
  1914. self.BuildTarget,
  1915. self.ToolChain,
  1916. self.MetaFile,
  1917. EdkLogger)
  1918. ## Override PCD setting (type, value, ...)
  1919. #
  1920. # @param ToPcd The PCD to be overridden
  1921. # @param FromPcd The PCD overriding from
  1922. #
  1923. def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):
  1924. #
  1925. # in case there's PCDs coming from FDF file, which have no type given.
  1926. # at this point, ToPcd.Type has the type found from dependent
  1927. # package
  1928. #
  1929. TokenCName = ToPcd.TokenCName
  1930. for PcdItem in GlobalData.MixedPcd:
  1931. if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
  1932. TokenCName = PcdItem[0]
  1933. break
  1934. if FromPcd is not None:
  1935. if ToPcd.Pending and FromPcd.Type:
  1936. ToPcd.Type = FromPcd.Type
  1937. elif ToPcd.Type and FromPcd.Type\
  1938. and ToPcd.Type != FromPcd.Type and ToPcd.Type in FromPcd.Type:
  1939. if ToPcd.Type.strip() == TAB_PCDS_DYNAMIC_EX:
  1940. ToPcd.Type = FromPcd.Type
  1941. elif ToPcd.Type and FromPcd.Type \
  1942. and ToPcd.Type != FromPcd.Type:
  1943. if Library:
  1944. Module = str(Module) + " 's library file (" + str(Library) + ")"
  1945. EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",
  1946. ExtraData="%s.%s is used as [%s] in module %s, but as [%s] in %s."\
  1947. % (ToPcd.TokenSpaceGuidCName, TokenCName,
  1948. ToPcd.Type, Module, FromPcd.Type, Msg),
  1949. File=self.MetaFile)
  1950. if FromPcd.MaxDatumSize:
  1951. ToPcd.MaxDatumSize = FromPcd.MaxDatumSize
  1952. ToPcd.MaxSizeUserSet = FromPcd.MaxDatumSize
  1953. if FromPcd.DefaultValue:
  1954. ToPcd.DefaultValue = FromPcd.DefaultValue
  1955. if FromPcd.TokenValue:
  1956. ToPcd.TokenValue = FromPcd.TokenValue
  1957. if FromPcd.DatumType:
  1958. ToPcd.DatumType = FromPcd.DatumType
  1959. if FromPcd.SkuInfoList:
  1960. ToPcd.SkuInfoList = FromPcd.SkuInfoList
  1961. if FromPcd.UserDefinedDefaultStoresFlag:
  1962. ToPcd.UserDefinedDefaultStoresFlag = FromPcd.UserDefinedDefaultStoresFlag
  1963. # Add Flexible PCD format parse
  1964. if ToPcd.DefaultValue:
  1965. try:
  1966. ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self.Workspace._GuidDict)(True)
  1967. except BadExpression as Value:
  1968. EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),
  1969. File=self.MetaFile)
  1970. # check the validation of datum
  1971. IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)
  1972. if not IsValid:
  1973. EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,
  1974. ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))
  1975. ToPcd.validateranges = FromPcd.validateranges
  1976. ToPcd.validlists = FromPcd.validlists
  1977. ToPcd.expressions = FromPcd.expressions
  1978. ToPcd.CustomAttribute = FromPcd.CustomAttribute
  1979. if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:
  1980. EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \
  1981. % (ToPcd.TokenSpaceGuidCName, TokenCName))
  1982. Value = ToPcd.DefaultValue
  1983. if not Value:
  1984. ToPcd.MaxDatumSize = '1'
  1985. elif Value[0] == 'L':
  1986. ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)
  1987. elif Value[0] == '{':
  1988. ToPcd.MaxDatumSize = str(len(Value.split(',')))
  1989. else:
  1990. ToPcd.MaxDatumSize = str(len(Value) - 1)
  1991. # apply default SKU for dynamic PCDS if specified one is not available
  1992. if (ToPcd.Type in PCD_DYNAMIC_TYPE_SET or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_SET) \
  1993. and not ToPcd.SkuInfoList:
  1994. if self.Platform.SkuName in self.Platform.SkuIds:
  1995. SkuName = self.Platform.SkuName
  1996. else:
  1997. SkuName = TAB_DEFAULT
  1998. ToPcd.SkuInfoList = {
  1999. SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)
  2000. }
  2001. ## Apply PCD setting defined platform to a module
  2002. #
  2003. # @param Module The module from which the PCD setting will be overridden
  2004. #
  2005. # @retval PCD_list The list PCDs with settings from platform
  2006. #
  2007. def ApplyPcdSetting(self, Module, Pcds, Library=""):
  2008. # for each PCD in module
  2009. for Name, Guid in Pcds:
  2010. PcdInModule = Pcds[Name, Guid]
  2011. # find out the PCD setting in platform
  2012. if (Name, Guid) in self.Platform.Pcds:
  2013. PcdInPlatform = self.Platform.Pcds[Name, Guid]
  2014. else:
  2015. PcdInPlatform = None
  2016. # then override the settings if any
  2017. self._OverridePcd(PcdInModule, PcdInPlatform, Module, Msg="DSC PCD sections", Library=Library)
  2018. # resolve the VariableGuid value
  2019. for SkuId in PcdInModule.SkuInfoList:
  2020. Sku = PcdInModule.SkuInfoList[SkuId]
  2021. if Sku.VariableGuid == '': continue
  2022. Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)
  2023. if Sku.VariableGuidValue is None:
  2024. PackageList = "\n\t".join(str(P) for P in self.PackageList)
  2025. EdkLogger.error(
  2026. 'build',
  2027. RESOURCE_NOT_AVAILABLE,
  2028. "Value of GUID [%s] is not found in" % Sku.VariableGuid,
  2029. ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \
  2030. % (Guid, Name, str(Module)),
  2031. File=self.MetaFile
  2032. )
  2033. # override PCD settings with module specific setting
  2034. if Module in self.Platform.Modules:
  2035. PlatformModule = self.Platform.Modules[str(Module)]
  2036. for Key in PlatformModule.Pcds:
  2037. if GlobalData.BuildOptionPcd:
  2038. for pcd in GlobalData.BuildOptionPcd:
  2039. (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd
  2040. if (TokenCName, TokenSpaceGuidCName) == Key and FieldName =="":
  2041. PlatformModule.Pcds[Key].DefaultValue = pcdvalue
  2042. PlatformModule.Pcds[Key].PcdValueFromComm = pcdvalue
  2043. break
  2044. Flag = False
  2045. if Key in Pcds:
  2046. ToPcd = Pcds[Key]
  2047. Flag = True
  2048. elif Key in GlobalData.MixedPcd:
  2049. for PcdItem in GlobalData.MixedPcd[Key]:
  2050. if PcdItem in Pcds:
  2051. ToPcd = Pcds[PcdItem]
  2052. Flag = True
  2053. break
  2054. if Flag:
  2055. self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)
  2056. # use PCD value to calculate the MaxDatumSize when it is not specified
  2057. for Name, Guid in Pcds:
  2058. Pcd = Pcds[Name, Guid]
  2059. if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:
  2060. Pcd.MaxSizeUserSet = None
  2061. Value = Pcd.DefaultValue
  2062. if not Value:
  2063. Pcd.MaxDatumSize = '1'
  2064. elif Value[0] == 'L':
  2065. Pcd.MaxDatumSize = str((len(Value) - 2) * 2)
  2066. elif Value[0] == '{':
  2067. Pcd.MaxDatumSize = str(len(Value.split(',')))
  2068. else:
  2069. Pcd.MaxDatumSize = str(len(Value) - 1)
  2070. return list(Pcds.values())
  2071. ## Calculate the priority value of the build option
  2072. #
  2073. # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
  2074. #
  2075. # @retval Value Priority value based on the priority list.
  2076. #
  2077. def CalculatePriorityValue(self, Key):
  2078. Target, ToolChain, Arch, CommandType, Attr = Key.split('_')
  2079. PriorityValue = 0x11111
  2080. if Target == TAB_STAR:
  2081. PriorityValue &= 0x01111
  2082. if ToolChain == TAB_STAR:
  2083. PriorityValue &= 0x10111
  2084. if Arch == TAB_STAR:
  2085. PriorityValue &= 0x11011
  2086. if CommandType == TAB_STAR:
  2087. PriorityValue &= 0x11101
  2088. if Attr == TAB_STAR:
  2089. PriorityValue &= 0x11110
  2090. return self.PrioList["0x%0.5x" % PriorityValue]
  2091. ## Expand * in build option key
  2092. #
  2093. # @param Options Options to be expanded
  2094. # @param ToolDef Use specified ToolDef instead of full version.
  2095. # This is needed during initialization to prevent
  2096. # infinite recursion betweeh BuildOptions,
  2097. # ToolDefinition, and this function.
  2098. #
  2099. # @retval options Options expanded
  2100. #
  2101. def _ExpandBuildOption(self, Options, ModuleStyle=None, ToolDef=None):
  2102. if not ToolDef:
  2103. ToolDef = self.ToolDefinition
  2104. BuildOptions = {}
  2105. FamilyMatch = False
  2106. FamilyIsNull = True
  2107. OverrideList = {}
  2108. #
  2109. # Construct a list contain the build options which need override.
  2110. #
  2111. for Key in Options:
  2112. #
  2113. # Key[0] -- tool family
  2114. # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE
  2115. #
  2116. if (Key[0] == self.BuildRuleFamily and
  2117. (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):
  2118. Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')
  2119. if (Target == self.BuildTarget or Target == TAB_STAR) and\
  2120. (ToolChain == self.ToolChain or ToolChain == TAB_STAR) and\
  2121. (Arch == self.Arch or Arch == TAB_STAR) and\
  2122. Options[Key].startswith("="):
  2123. if OverrideList.get(Key[1]) is not None:
  2124. OverrideList.pop(Key[1])
  2125. OverrideList[Key[1]] = Options[Key]
  2126. #
  2127. # Use the highest priority value.
  2128. #
  2129. if (len(OverrideList) >= 2):
  2130. KeyList = list(OverrideList.keys())
  2131. for Index in range(len(KeyList)):
  2132. NowKey = KeyList[Index]
  2133. Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")
  2134. for Index1 in range(len(KeyList) - Index - 1):
  2135. NextKey = KeyList[Index1 + Index + 1]
  2136. #
  2137. # Compare two Key, if one is included by another, choose the higher priority one
  2138. #
  2139. Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")
  2140. if (Target1 == Target2 or Target1 == TAB_STAR or Target2 == TAB_STAR) and\
  2141. (ToolChain1 == ToolChain2 or ToolChain1 == TAB_STAR or ToolChain2 == TAB_STAR) and\
  2142. (Arch1 == Arch2 or Arch1 == TAB_STAR or Arch2 == TAB_STAR) and\
  2143. (CommandType1 == CommandType2 or CommandType1 == TAB_STAR or CommandType2 == TAB_STAR) and\
  2144. (Attr1 == Attr2 or Attr1 == TAB_STAR or Attr2 == TAB_STAR):
  2145. if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):
  2146. if Options.get((self.BuildRuleFamily, NextKey)) is not None:
  2147. Options.pop((self.BuildRuleFamily, NextKey))
  2148. else:
  2149. if Options.get((self.BuildRuleFamily, NowKey)) is not None:
  2150. Options.pop((self.BuildRuleFamily, NowKey))
  2151. for Key in Options:
  2152. if ModuleStyle is not None and len (Key) > 2:
  2153. # Check Module style is EDK or EDKII.
  2154. # Only append build option for the matched style module.
  2155. if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
  2156. continue
  2157. elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
  2158. continue
  2159. Family = Key[0]
  2160. Target, Tag, Arch, Tool, Attr = Key[1].split("_")
  2161. # if tool chain family doesn't match, skip it
  2162. if Tool in ToolDef and Family != "":
  2163. FamilyIsNull = False
  2164. if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
  2165. if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
  2166. continue
  2167. elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
  2168. continue
  2169. FamilyMatch = True
  2170. # expand any wildcard
  2171. if Target == TAB_STAR or Target == self.BuildTarget:
  2172. if Tag == TAB_STAR or Tag == self.ToolChain:
  2173. if Arch == TAB_STAR or Arch == self.Arch:
  2174. if Tool not in BuildOptions:
  2175. BuildOptions[Tool] = {}
  2176. if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
  2177. BuildOptions[Tool][Attr] = Options[Key]
  2178. else:
  2179. # append options for the same tool except PATH
  2180. if Attr != 'PATH':
  2181. BuildOptions[Tool][Attr] += " " + Options[Key]
  2182. else:
  2183. BuildOptions[Tool][Attr] = Options[Key]
  2184. # Build Option Family has been checked, which need't to be checked again for family.
  2185. if FamilyMatch or FamilyIsNull:
  2186. return BuildOptions
  2187. for Key in Options:
  2188. if ModuleStyle is not None and len (Key) > 2:
  2189. # Check Module style is EDK or EDKII.
  2190. # Only append build option for the matched style module.
  2191. if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:
  2192. continue
  2193. elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:
  2194. continue
  2195. Family = Key[0]
  2196. Target, Tag, Arch, Tool, Attr = Key[1].split("_")
  2197. # if tool chain family doesn't match, skip it
  2198. if Tool not in ToolDef or Family == "":
  2199. continue
  2200. # option has been added before
  2201. if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
  2202. continue
  2203. # expand any wildcard
  2204. if Target == TAB_STAR or Target == self.BuildTarget:
  2205. if Tag == TAB_STAR or Tag == self.ToolChain:
  2206. if Arch == TAB_STAR or Arch == self.Arch:
  2207. if Tool not in BuildOptions:
  2208. BuildOptions[Tool] = {}
  2209. if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):
  2210. BuildOptions[Tool][Attr] = Options[Key]
  2211. else:
  2212. # append options for the same tool except PATH
  2213. if Attr != 'PATH':
  2214. BuildOptions[Tool][Attr] += " " + Options[Key]
  2215. else:
  2216. BuildOptions[Tool][Attr] = Options[Key]
  2217. return BuildOptions
  2218. ## Append build options in platform to a module
  2219. #
  2220. # @param Module The module to which the build options will be appended
  2221. #
  2222. # @retval options The options appended with build options in platform
  2223. #
  2224. def ApplyBuildOption(self, Module):
  2225. # Get the different options for the different style module
  2226. PlatformOptions = self.EdkIIBuildOption
  2227. ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)
  2228. ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)
  2229. ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)
  2230. if Module in self.Platform.Modules:
  2231. PlatformModule = self.Platform.Modules[str(Module)]
  2232. PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)
  2233. else:
  2234. PlatformModuleOptions = {}
  2235. BuildRuleOrder = None
  2236. for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
  2237. for Tool in Options:
  2238. for Attr in Options[Tool]:
  2239. if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
  2240. BuildRuleOrder = Options[Tool][Attr]
  2241. AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) +
  2242. list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) +
  2243. list(self.ToolDefinition.keys()))
  2244. BuildOptions = defaultdict(lambda: defaultdict(str))
  2245. for Tool in AllTools:
  2246. for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:
  2247. if Tool not in Options:
  2248. continue
  2249. for Attr in Options[Tool]:
  2250. #
  2251. # Do not generate it in Makefile
  2252. #
  2253. if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
  2254. continue
  2255. Value = Options[Tool][Attr]
  2256. # check if override is indicated
  2257. if Value.startswith('='):
  2258. BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])
  2259. else:
  2260. if Attr != 'PATH':
  2261. BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)
  2262. else:
  2263. BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)
  2264. return BuildOptions, BuildRuleOrder
  2265. #
  2266. # extend lists contained in a dictionary with lists stored in another dictionary
  2267. # if CopyToDict is not derived from DefaultDict(list) then this may raise exception
  2268. #
  2269. def ExtendCopyDictionaryLists(CopyToDict, CopyFromDict):
  2270. for Key in CopyFromDict:
  2271. CopyToDict[Key].extend(CopyFromDict[Key])
  2272. # Create a directory specified by a set of path elements and return the full path
  2273. def _MakeDir(PathList):
  2274. RetVal = path.join(*PathList)
  2275. CreateDirectory(RetVal)
  2276. return RetVal
  2277. ## ModuleAutoGen class
  2278. #
  2279. # This class encapsules the AutoGen behaviors for the build tools. In addition to
  2280. # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according
  2281. # to the [depex] section in module's inf file.
  2282. #
  2283. class ModuleAutoGen(AutoGen):
  2284. # call super().__init__ then call the worker function with different parameter count
  2285. def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
  2286. if not hasattr(self, "_Init"):
  2287. self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args)
  2288. self._Init = True
  2289. ## Cache the timestamps of metafiles of every module in a class attribute
  2290. #
  2291. TimeDict = {}
  2292. def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):
  2293. # check if this module is employed by active platform
  2294. if not PlatformAutoGen(Workspace, args[0], Target, Toolchain, Arch).ValidModule(MetaFile):
  2295. EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \
  2296. % (MetaFile, Arch))
  2297. return None
  2298. return super(ModuleAutoGen, cls).__new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)
  2299. ## Initialize ModuleAutoGen
  2300. #
  2301. # @param Workspace EdkIIWorkspaceBuild object
  2302. # @param ModuleFile The path of module file
  2303. # @param Target Build target (DEBUG, RELEASE)
  2304. # @param Toolchain Name of tool chain
  2305. # @param Arch The arch the module supports
  2306. # @param PlatformFile Platform meta-file
  2307. #
  2308. def _InitWorker(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):
  2309. EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))
  2310. GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)
  2311. self.Workspace = Workspace
  2312. self.WorkspaceDir = Workspace.WorkspaceDir
  2313. self.MetaFile = ModuleFile
  2314. self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)
  2315. self.SourceDir = self.MetaFile.SubDir
  2316. self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)
  2317. self.SourceOverrideDir = None
  2318. # use overridden path defined in DSC file
  2319. if self.MetaFile.Key in GlobalData.gOverrideDir:
  2320. self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]
  2321. self.ToolChain = Toolchain
  2322. self.BuildTarget = Target
  2323. self.Arch = Arch
  2324. self.ToolChainFamily = self.PlatformInfo.ToolChainFamily
  2325. self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily
  2326. self.IsCodeFileCreated = False
  2327. self.IsAsBuiltInfCreated = False
  2328. self.DepexGenerated = False
  2329. self.BuildDatabase = self.Workspace.BuildDatabase
  2330. self.BuildRuleOrder = None
  2331. self.BuildTime = 0
  2332. self._PcdComments = OrderedListDict()
  2333. self._GuidComments = OrderedListDict()
  2334. self._ProtocolComments = OrderedListDict()
  2335. self._PpiComments = OrderedListDict()
  2336. self._BuildTargets = None
  2337. self._IntroBuildTargetList = None
  2338. self._FinalBuildTargetList = None
  2339. self._FileTypes = None
  2340. self.AutoGenDepSet = set()
  2341. self.ReferenceModules = []
  2342. self.ConstPcd = {}
  2343. def __repr__(self):
  2344. return "%s [%s]" % (self.MetaFile, self.Arch)
  2345. # Get FixedAtBuild Pcds of this Module
  2346. @cached_property
  2347. def FixedAtBuildPcds(self):
  2348. RetVal = []
  2349. for Pcd in self.ModulePcdList:
  2350. if Pcd.Type != TAB_PCDS_FIXED_AT_BUILD:
  2351. continue
  2352. if Pcd not in RetVal:
  2353. RetVal.append(Pcd)
  2354. return RetVal
  2355. @cached_property
  2356. def FixedVoidTypePcds(self):
  2357. RetVal = {}
  2358. for Pcd in self.FixedAtBuildPcds:
  2359. if Pcd.DatumType == TAB_VOID:
  2360. if '{}.{}'.format(Pcd.TokenSpaceGuidCName, Pcd.TokenCName) not in RetVal:
  2361. RetVal['{}.{}'.format(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)] = Pcd.DefaultValue
  2362. return RetVal
  2363. @property
  2364. def UniqueBaseName(self):
  2365. BaseName = self.Name
  2366. for Module in self.PlatformInfo.ModuleAutoGenList:
  2367. if Module.MetaFile == self.MetaFile:
  2368. continue
  2369. if Module.Name == self.Name:
  2370. if uuid.UUID(Module.Guid) == uuid.UUID(self.Guid):
  2371. EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'
  2372. ' %s\n %s' % (Module.MetaFile, self.MetaFile))
  2373. BaseName = '%s_%s' % (self.Name, self.Guid)
  2374. return BaseName
  2375. # Macros could be used in build_rule.txt (also Makefile)
  2376. @cached_property
  2377. def Macros(self):
  2378. return OrderedDict((
  2379. ("WORKSPACE" ,self.WorkspaceDir),
  2380. ("MODULE_NAME" ,self.Name),
  2381. ("MODULE_NAME_GUID" ,self.UniqueBaseName),
  2382. ("MODULE_GUID" ,self.Guid),
  2383. ("MODULE_VERSION" ,self.Version),
  2384. ("MODULE_TYPE" ,self.ModuleType),
  2385. ("MODULE_FILE" ,str(self.MetaFile)),
  2386. ("MODULE_FILE_BASE_NAME" ,self.MetaFile.BaseName),
  2387. ("MODULE_RELATIVE_DIR" ,self.SourceDir),
  2388. ("MODULE_DIR" ,self.SourceDir),
  2389. ("BASE_NAME" ,self.Name),
  2390. ("ARCH" ,self.Arch),
  2391. ("TOOLCHAIN" ,self.ToolChain),
  2392. ("TOOLCHAIN_TAG" ,self.ToolChain),
  2393. ("TOOL_CHAIN_TAG" ,self.ToolChain),
  2394. ("TARGET" ,self.BuildTarget),
  2395. ("BUILD_DIR" ,self.PlatformInfo.BuildDir),
  2396. ("BIN_DIR" ,os.path.join(self.PlatformInfo.BuildDir, self.Arch)),
  2397. ("LIB_DIR" ,os.path.join(self.PlatformInfo.BuildDir, self.Arch)),
  2398. ("MODULE_BUILD_DIR" ,self.BuildDir),
  2399. ("OUTPUT_DIR" ,self.OutputDir),
  2400. ("DEBUG_DIR" ,self.DebugDir),
  2401. ("DEST_DIR_OUTPUT" ,self.OutputDir),
  2402. ("DEST_DIR_DEBUG" ,self.DebugDir),
  2403. ("PLATFORM_NAME" ,self.PlatformInfo.Name),
  2404. ("PLATFORM_GUID" ,self.PlatformInfo.Guid),
  2405. ("PLATFORM_VERSION" ,self.PlatformInfo.Version),
  2406. ("PLATFORM_RELATIVE_DIR" ,self.PlatformInfo.SourceDir),
  2407. ("PLATFORM_DIR" ,mws.join(self.WorkspaceDir, self.PlatformInfo.SourceDir)),
  2408. ("PLATFORM_OUTPUT_DIR" ,self.PlatformInfo.OutputDir),
  2409. ("FFS_OUTPUT_DIR" ,self.FfsOutputDir)
  2410. ))
  2411. ## Return the module build data object
  2412. @cached_property
  2413. def Module(self):
  2414. return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]
  2415. ## Return the module name
  2416. @cached_property
  2417. def Name(self):
  2418. return self.Module.BaseName
  2419. ## Return the module DxsFile if exist
  2420. @cached_property
  2421. def DxsFile(self):
  2422. return self.Module.DxsFile
  2423. ## Return the module meta-file GUID
  2424. @cached_property
  2425. def Guid(self):
  2426. #
  2427. # To build same module more than once, the module path with FILE_GUID overridden has
  2428. # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path
  2429. # in DSC. The overridden GUID can be retrieved from file name
  2430. #
  2431. if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path):
  2432. #
  2433. # Length of GUID is 36
  2434. #
  2435. return os.path.basename(self.MetaFile.Path)[:36]
  2436. return self.Module.Guid
  2437. ## Return the module version
  2438. @cached_property
  2439. def Version(self):
  2440. return self.Module.Version
  2441. ## Return the module type
  2442. @cached_property
  2443. def ModuleType(self):
  2444. return self.Module.ModuleType
  2445. ## Return the component type (for Edk.x style of module)
  2446. @cached_property
  2447. def ComponentType(self):
  2448. return self.Module.ComponentType
  2449. ## Return the build type
  2450. @cached_property
  2451. def BuildType(self):
  2452. return self.Module.BuildType
  2453. ## Return the PCD_IS_DRIVER setting
  2454. @cached_property
  2455. def PcdIsDriver(self):
  2456. return self.Module.PcdIsDriver
  2457. ## Return the autogen version, i.e. module meta-file version
  2458. @cached_property
  2459. def AutoGenVersion(self):
  2460. return self.Module.AutoGenVersion
  2461. ## Check if the module is library or not
  2462. @cached_property
  2463. def IsLibrary(self):
  2464. return bool(self.Module.LibraryClass)
  2465. ## Check if the module is binary module or not
  2466. @cached_property
  2467. def IsBinaryModule(self):
  2468. return self.Module.IsBinaryModule
  2469. ## Return the directory to store intermediate files of the module
  2470. @cached_property
  2471. def BuildDir(self):
  2472. return _MakeDir((
  2473. self.PlatformInfo.BuildDir,
  2474. self.Arch,
  2475. self.SourceDir,
  2476. self.MetaFile.BaseName
  2477. ))
  2478. ## Return the directory to store the intermediate object files of the module
  2479. @cached_property
  2480. def OutputDir(self):
  2481. return _MakeDir((self.BuildDir, "OUTPUT"))
  2482. ## Return the directory path to store ffs file
  2483. @cached_property
  2484. def FfsOutputDir(self):
  2485. if GlobalData.gFdfParser:
  2486. return path.join(self.PlatformInfo.BuildDir, TAB_FV_DIRECTORY, "Ffs", self.Guid + self.Name)
  2487. return ''
  2488. ## Return the directory to store auto-gened source files of the module
  2489. @cached_property
  2490. def DebugDir(self):
  2491. return _MakeDir((self.BuildDir, "DEBUG"))
  2492. ## Return the path of custom file
  2493. @cached_property
  2494. def CustomMakefile(self):
  2495. RetVal = {}
  2496. for Type in self.Module.CustomMakefile:
  2497. MakeType = gMakeTypeMap[Type] if Type in gMakeTypeMap else 'nmake'
  2498. if self.SourceOverrideDir is not None:
  2499. File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])
  2500. if not os.path.exists(File):
  2501. File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
  2502. else:
  2503. File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])
  2504. RetVal[MakeType] = File
  2505. return RetVal
  2506. ## Return the directory of the makefile
  2507. #
  2508. # @retval string The directory string of module's makefile
  2509. #
  2510. @cached_property
  2511. def MakeFileDir(self):
  2512. return self.BuildDir
  2513. ## Return build command string
  2514. #
  2515. # @retval string Build command string
  2516. #
  2517. @cached_property
  2518. def BuildCommand(self):
  2519. return self.PlatformInfo.BuildCommand
  2520. ## Get object list of all packages the module and its dependent libraries belong to
  2521. #
  2522. # @retval list The list of package object
  2523. #
  2524. @cached_property
  2525. def DerivedPackageList(self):
  2526. PackageList = []
  2527. for M in [self.Module] + self.DependentLibraryList:
  2528. for Package in M.Packages:
  2529. if Package in PackageList:
  2530. continue
  2531. PackageList.append(Package)
  2532. return PackageList
  2533. ## Get the depex string
  2534. #
  2535. # @return : a string contain all depex expression.
  2536. def _GetDepexExpresionString(self):
  2537. DepexStr = ''
  2538. DepexList = []
  2539. ## DPX_SOURCE IN Define section.
  2540. if self.Module.DxsFile:
  2541. return DepexStr
  2542. for M in [self.Module] + self.DependentLibraryList:
  2543. Filename = M.MetaFile.Path
  2544. InfObj = InfSectionParser.InfSectionParser(Filename)
  2545. DepexExpressionList = InfObj.GetDepexExpresionList()
  2546. for DepexExpression in DepexExpressionList:
  2547. for key in DepexExpression:
  2548. Arch, ModuleType = key
  2549. DepexExpr = [x for x in DepexExpression[key] if not str(x).startswith('#')]
  2550. # the type of build module is USER_DEFINED.
  2551. # All different DEPEX section tags would be copied into the As Built INF file
  2552. # and there would be separate DEPEX section tags
  2553. if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:
  2554. if (Arch.upper() == self.Arch.upper()) and (ModuleType.upper() != TAB_ARCH_COMMON):
  2555. DepexList.append({(Arch, ModuleType): DepexExpr})
  2556. else:
  2557. if Arch.upper() == TAB_ARCH_COMMON or \
  2558. (Arch.upper() == self.Arch.upper() and \
  2559. ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):
  2560. DepexList.append({(Arch, ModuleType): DepexExpr})
  2561. #the type of build module is USER_DEFINED.
  2562. if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:
  2563. for Depex in DepexList:
  2564. for key in Depex:
  2565. DepexStr += '[Depex.%s.%s]\n' % key
  2566. DepexStr += '\n'.join('# '+ val for val in Depex[key])
  2567. DepexStr += '\n\n'
  2568. if not DepexStr:
  2569. return '[Depex.%s]\n' % self.Arch
  2570. return DepexStr
  2571. #the type of build module not is USER_DEFINED.
  2572. Count = 0
  2573. for Depex in DepexList:
  2574. Count += 1
  2575. if DepexStr != '':
  2576. DepexStr += ' AND '
  2577. DepexStr += '('
  2578. for D in Depex.values():
  2579. DepexStr += ' '.join(val for val in D)
  2580. Index = DepexStr.find('END')
  2581. if Index > -1 and Index == len(DepexStr) - 3:
  2582. DepexStr = DepexStr[:-3]
  2583. DepexStr = DepexStr.strip()
  2584. DepexStr += ')'
  2585. if Count == 1:
  2586. DepexStr = DepexStr.lstrip('(').rstrip(')').strip()
  2587. if not DepexStr:
  2588. return '[Depex.%s]\n' % self.Arch
  2589. return '[Depex.%s]\n# ' % self.Arch + DepexStr
  2590. ## Merge dependency expression
  2591. #
  2592. # @retval list The token list of the dependency expression after parsed
  2593. #
  2594. @cached_property
  2595. def DepexList(self):
  2596. if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
  2597. return {}
  2598. DepexList = []
  2599. #
  2600. # Append depex from dependent libraries, if not "BEFORE", "AFTER" expression
  2601. #
  2602. for M in [self.Module] + self.DependentLibraryList:
  2603. Inherited = False
  2604. for D in M.Depex[self.Arch, self.ModuleType]:
  2605. if DepexList != []:
  2606. DepexList.append('AND')
  2607. DepexList.append('(')
  2608. #replace D with value if D is FixedAtBuild PCD
  2609. NewList = []
  2610. for item in D:
  2611. if '.' not in item:
  2612. NewList.append(item)
  2613. else:
  2614. if item not in self.FixedVoidTypePcds:
  2615. EdkLogger.error("build", FORMAT_INVALID, "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type in the module.".format(item))
  2616. else:
  2617. Value = self.FixedVoidTypePcds[item]
  2618. if len(Value.split(',')) != 16:
  2619. EdkLogger.error("build", FORMAT_INVALID,
  2620. "{} used in [Depex] section should be used as FixedAtBuild type and VOID* datum type and 16 bytes in the module.".format(item))
  2621. NewList.append(Value)
  2622. DepexList.extend(NewList)
  2623. if DepexList[-1] == 'END': # no need of a END at this time
  2624. DepexList.pop()
  2625. DepexList.append(')')
  2626. Inherited = True
  2627. if Inherited:
  2628. EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))
  2629. if 'BEFORE' in DepexList or 'AFTER' in DepexList:
  2630. break
  2631. if len(DepexList) > 0:
  2632. EdkLogger.verbose('')
  2633. return {self.ModuleType:DepexList}
  2634. ## Merge dependency expression
  2635. #
  2636. # @retval list The token list of the dependency expression after parsed
  2637. #
  2638. @cached_property
  2639. def DepexExpressionDict(self):
  2640. if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:
  2641. return {}
  2642. DepexExpressionString = ''
  2643. #
  2644. # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion
  2645. #
  2646. for M in [self.Module] + self.DependentLibraryList:
  2647. Inherited = False
  2648. for D in M.DepexExpression[self.Arch, self.ModuleType]:
  2649. if DepexExpressionString != '':
  2650. DepexExpressionString += ' AND '
  2651. DepexExpressionString += '('
  2652. DepexExpressionString += D
  2653. DepexExpressionString = DepexExpressionString.rstrip('END').strip()
  2654. DepexExpressionString += ')'
  2655. Inherited = True
  2656. if Inherited:
  2657. EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionString))
  2658. if 'BEFORE' in DepexExpressionString or 'AFTER' in DepexExpressionString:
  2659. break
  2660. if len(DepexExpressionString) > 0:
  2661. EdkLogger.verbose('')
  2662. return {self.ModuleType:DepexExpressionString}
  2663. # Get the tiano core user extension, it is contain dependent library.
  2664. # @retval: a list contain tiano core userextension.
  2665. #
  2666. def _GetTianoCoreUserExtensionList(self):
  2667. TianoCoreUserExtentionList = []
  2668. for M in [self.Module] + self.DependentLibraryList:
  2669. Filename = M.MetaFile.Path
  2670. InfObj = InfSectionParser.InfSectionParser(Filename)
  2671. TianoCoreUserExtenList = InfObj.GetUserExtensionTianoCore()
  2672. for TianoCoreUserExtent in TianoCoreUserExtenList:
  2673. for Section in TianoCoreUserExtent:
  2674. ItemList = Section.split(TAB_SPLIT)
  2675. Arch = self.Arch
  2676. if len(ItemList) == 4:
  2677. Arch = ItemList[3]
  2678. if Arch.upper() == TAB_ARCH_COMMON or Arch.upper() == self.Arch.upper():
  2679. TianoCoreList = []
  2680. TianoCoreList.extend([TAB_SECTION_START + Section + TAB_SECTION_END])
  2681. TianoCoreList.extend(TianoCoreUserExtent[Section][:])
  2682. TianoCoreList.append('\n')
  2683. TianoCoreUserExtentionList.append(TianoCoreList)
  2684. return TianoCoreUserExtentionList
  2685. ## Return the list of specification version required for the module
  2686. #
  2687. # @retval list The list of specification defined in module file
  2688. #
  2689. @cached_property
  2690. def Specification(self):
  2691. return self.Module.Specification
  2692. ## Tool option for the module build
  2693. #
  2694. # @param PlatformInfo The object of PlatformBuildInfo
  2695. # @retval dict The dict containing valid options
  2696. #
  2697. @cached_property
  2698. def BuildOption(self):
  2699. RetVal, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)
  2700. if self.BuildRuleOrder:
  2701. self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]
  2702. return RetVal
  2703. ## Get include path list from tool option for the module build
  2704. #
  2705. # @retval list The include path list
  2706. #
  2707. @cached_property
  2708. def BuildOptionIncPathList(self):
  2709. #
  2710. # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT
  2711. # is the former use /I , the Latter used -I to specify include directories
  2712. #
  2713. if self.PlatformInfo.ToolChainFamily in (TAB_COMPILER_MSFT):
  2714. BuildOptIncludeRegEx = gBuildOptIncludePatternMsft
  2715. elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):
  2716. BuildOptIncludeRegEx = gBuildOptIncludePatternOther
  2717. else:
  2718. #
  2719. # New ToolChainFamily, don't known whether there is option to specify include directories
  2720. #
  2721. return []
  2722. RetVal = []
  2723. for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):
  2724. try:
  2725. FlagOption = self.BuildOption[Tool]['FLAGS']
  2726. except KeyError:
  2727. FlagOption = ''
  2728. if self.ToolChainFamily != 'RVCT':
  2729. IncPathList = [NormPath(Path, self.Macros) for Path in BuildOptIncludeRegEx.findall(FlagOption)]
  2730. else:
  2731. #
  2732. # RVCT may specify a list of directory seperated by commas
  2733. #
  2734. IncPathList = []
  2735. for Path in BuildOptIncludeRegEx.findall(FlagOption):
  2736. PathList = GetSplitList(Path, TAB_COMMA_SPLIT)
  2737. IncPathList.extend(NormPath(PathEntry, self.Macros) for PathEntry in PathList)
  2738. #
  2739. # EDK II modules must not reference header files outside of the packages they depend on or
  2740. # within the module's directory tree. Report error if violation.
  2741. #
  2742. for Path in IncPathList:
  2743. if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):
  2744. ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)
  2745. EdkLogger.error("build",
  2746. PARAMETER_INVALID,
  2747. ExtraData=ErrMsg,
  2748. File=str(self.MetaFile))
  2749. RetVal += IncPathList
  2750. return RetVal
  2751. ## Return a list of files which can be built from source
  2752. #
  2753. # What kind of files can be built is determined by build rules in
  2754. # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.
  2755. #
  2756. @cached_property
  2757. def SourceFileList(self):
  2758. RetVal = []
  2759. ToolChainTagSet = {"", TAB_STAR, self.ToolChain}
  2760. ToolChainFamilySet = {"", TAB_STAR, self.ToolChainFamily, self.BuildRuleFamily}
  2761. for F in self.Module.Sources:
  2762. # match tool chain
  2763. if F.TagName not in ToolChainTagSet:
  2764. EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "
  2765. "but [%s] is currently used" % (F.TagName, str(F), self.ToolChain))
  2766. continue
  2767. # match tool chain family or build rule family
  2768. if F.ToolChainFamily not in ToolChainFamilySet:
  2769. EdkLogger.debug(
  2770. EdkLogger.DEBUG_0,
  2771. "The file [%s] must be built by tools of [%s], " \
  2772. "but current toolchain family is [%s], buildrule family is [%s]" \
  2773. % (str(F), F.ToolChainFamily, self.ToolChainFamily, self.BuildRuleFamily))
  2774. continue
  2775. # add the file path into search path list for file including
  2776. if F.Dir not in self.IncludePathList:
  2777. self.IncludePathList.insert(0, F.Dir)
  2778. RetVal.append(F)
  2779. self._MatchBuildRuleOrder(RetVal)
  2780. for F in RetVal:
  2781. self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)
  2782. return RetVal
  2783. def _MatchBuildRuleOrder(self, FileList):
  2784. Order_Dict = {}
  2785. self.BuildOption
  2786. for SingleFile in FileList:
  2787. if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules:
  2788. key = SingleFile.Path.rsplit(SingleFile.Ext,1)[0]
  2789. if key in Order_Dict:
  2790. Order_Dict[key].append(SingleFile.Ext)
  2791. else:
  2792. Order_Dict[key] = [SingleFile.Ext]
  2793. RemoveList = []
  2794. for F in Order_Dict:
  2795. if len(Order_Dict[F]) > 1:
  2796. Order_Dict[F].sort(key=lambda i: self.BuildRuleOrder.index(i))
  2797. for Ext in Order_Dict[F][1:]:
  2798. RemoveList.append(F + Ext)
  2799. for item in RemoveList:
  2800. FileList.remove(item)
  2801. return FileList
  2802. ## Return the list of unicode files
  2803. @cached_property
  2804. def UnicodeFileList(self):
  2805. return self.FileTypes.get(TAB_UNICODE_FILE,[])
  2806. ## Return the list of vfr files
  2807. @cached_property
  2808. def VfrFileList(self):
  2809. return self.FileTypes.get(TAB_VFR_FILE, [])
  2810. ## Return the list of Image Definition files
  2811. @cached_property
  2812. def IdfFileList(self):
  2813. return self.FileTypes.get(TAB_IMAGE_FILE,[])
  2814. ## Return a list of files which can be built from binary
  2815. #
  2816. # "Build" binary files are just to copy them to build directory.
  2817. #
  2818. # @retval list The list of files which can be built later
  2819. #
  2820. @cached_property
  2821. def BinaryFileList(self):
  2822. RetVal = []
  2823. for F in self.Module.Binaries:
  2824. if F.Target not in [TAB_ARCH_COMMON, TAB_STAR] and F.Target != self.BuildTarget:
  2825. continue
  2826. RetVal.append(F)
  2827. self._ApplyBuildRule(F, F.Type, BinaryFileList=RetVal)
  2828. return RetVal
  2829. @cached_property
  2830. def BuildRules(self):
  2831. RetVal = {}
  2832. BuildRuleDatabase = self.PlatformInfo.BuildRule
  2833. for Type in BuildRuleDatabase.FileTypeList:
  2834. #first try getting build rule by BuildRuleFamily
  2835. RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]
  2836. if not RuleObject:
  2837. # build type is always module type, but ...
  2838. if self.ModuleType != self.BuildType:
  2839. RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]
  2840. #second try getting build rule by ToolChainFamily
  2841. if not RuleObject:
  2842. RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]
  2843. if not RuleObject:
  2844. # build type is always module type, but ...
  2845. if self.ModuleType != self.BuildType:
  2846. RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]
  2847. if not RuleObject:
  2848. continue
  2849. RuleObject = RuleObject.Instantiate(self.Macros)
  2850. RetVal[Type] = RuleObject
  2851. for Ext in RuleObject.SourceFileExtList:
  2852. RetVal[Ext] = RuleObject
  2853. return RetVal
  2854. def _ApplyBuildRule(self, File, FileType, BinaryFileList=None):
  2855. if self._BuildTargets is None:
  2856. self._IntroBuildTargetList = set()
  2857. self._FinalBuildTargetList = set()
  2858. self._BuildTargets = defaultdict(set)
  2859. self._FileTypes = defaultdict(set)
  2860. if not BinaryFileList:
  2861. BinaryFileList = self.BinaryFileList
  2862. SubDirectory = os.path.join(self.OutputDir, File.SubDir)
  2863. if not os.path.exists(SubDirectory):
  2864. CreateDirectory(SubDirectory)
  2865. LastTarget = None
  2866. RuleChain = set()
  2867. SourceList = [File]
  2868. Index = 0
  2869. #
  2870. # Make sure to get build rule order value
  2871. #
  2872. self.BuildOption
  2873. while Index < len(SourceList):
  2874. Source = SourceList[Index]
  2875. Index = Index + 1
  2876. if Source != File:
  2877. CreateDirectory(Source.Dir)
  2878. if File.IsBinary and File == Source and File in BinaryFileList:
  2879. # Skip all files that are not binary libraries
  2880. if not self.IsLibrary:
  2881. continue
  2882. RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]
  2883. elif FileType in self.BuildRules:
  2884. RuleObject = self.BuildRules[FileType]
  2885. elif Source.Ext in self.BuildRules:
  2886. RuleObject = self.BuildRules[Source.Ext]
  2887. else:
  2888. # stop at no more rules
  2889. if LastTarget:
  2890. self._FinalBuildTargetList.add(LastTarget)
  2891. break
  2892. FileType = RuleObject.SourceFileType
  2893. self._FileTypes[FileType].add(Source)
  2894. # stop at STATIC_LIBRARY for library
  2895. if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
  2896. if LastTarget:
  2897. self._FinalBuildTargetList.add(LastTarget)
  2898. break
  2899. Target = RuleObject.Apply(Source, self.BuildRuleOrder)
  2900. if not Target:
  2901. if LastTarget:
  2902. self._FinalBuildTargetList.add(LastTarget)
  2903. break
  2904. elif not Target.Outputs:
  2905. # Only do build for target with outputs
  2906. self._FinalBuildTargetList.add(Target)
  2907. self._BuildTargets[FileType].add(Target)
  2908. if not Source.IsBinary and Source == File:
  2909. self._IntroBuildTargetList.add(Target)
  2910. # to avoid cyclic rule
  2911. if FileType in RuleChain:
  2912. break
  2913. RuleChain.add(FileType)
  2914. SourceList.extend(Target.Outputs)
  2915. LastTarget = Target
  2916. FileType = TAB_UNKNOWN_FILE
  2917. @cached_property
  2918. def Targets(self):
  2919. if self._BuildTargets is None:
  2920. self._IntroBuildTargetList = set()
  2921. self._FinalBuildTargetList = set()
  2922. self._BuildTargets = defaultdict(set)
  2923. self._FileTypes = defaultdict(set)
  2924. #TRICK: call SourceFileList property to apply build rule for source files
  2925. self.SourceFileList
  2926. #TRICK: call _GetBinaryFileList to apply build rule for binary files
  2927. self.BinaryFileList
  2928. return self._BuildTargets
  2929. @cached_property
  2930. def IntroTargetList(self):
  2931. self.Targets
  2932. return self._IntroBuildTargetList
  2933. @cached_property
  2934. def CodaTargetList(self):
  2935. self.Targets
  2936. return self._FinalBuildTargetList
  2937. @cached_property
  2938. def FileTypes(self):
  2939. self.Targets
  2940. return self._FileTypes
  2941. ## Get the list of package object the module depends on
  2942. #
  2943. # @retval list The package object list
  2944. #
  2945. @cached_property
  2946. def DependentPackageList(self):
  2947. return self.Module.Packages
  2948. ## Return the list of auto-generated code file
  2949. #
  2950. # @retval list The list of auto-generated file
  2951. #
  2952. @cached_property
  2953. def AutoGenFileList(self):
  2954. AutoGenUniIdf = self.BuildType != 'UEFI_HII'
  2955. UniStringBinBuffer = BytesIO()
  2956. IdfGenBinBuffer = BytesIO()
  2957. RetVal = {}
  2958. AutoGenC = TemplateString()
  2959. AutoGenH = TemplateString()
  2960. StringH = TemplateString()
  2961. StringIdf = TemplateString()
  2962. GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, AutoGenUniIdf, UniStringBinBuffer, StringIdf, AutoGenUniIdf, IdfGenBinBuffer)
  2963. #
  2964. # AutoGen.c is generated if there are library classes in inf, or there are object files
  2965. #
  2966. if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0
  2967. or TAB_OBJECT_FILE in self.FileTypes):
  2968. AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)
  2969. RetVal[AutoFile] = str(AutoGenC)
  2970. self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
  2971. if str(AutoGenH) != "":
  2972. AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)
  2973. RetVal[AutoFile] = str(AutoGenH)
  2974. self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
  2975. if str(StringH) != "":
  2976. AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)
  2977. RetVal[AutoFile] = str(StringH)
  2978. self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
  2979. if UniStringBinBuffer is not None and UniStringBinBuffer.getvalue() != b"":
  2980. AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)
  2981. RetVal[AutoFile] = UniStringBinBuffer.getvalue()
  2982. AutoFile.IsBinary = True
  2983. self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
  2984. if UniStringBinBuffer is not None:
  2985. UniStringBinBuffer.close()
  2986. if str(StringIdf) != "":
  2987. AutoFile = PathClass(gAutoGenImageDefFileName % {"module_name":self.Name}, self.DebugDir)
  2988. RetVal[AutoFile] = str(StringIdf)
  2989. self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
  2990. if IdfGenBinBuffer is not None and IdfGenBinBuffer.getvalue() != b"":
  2991. AutoFile = PathClass(gAutoGenIdfFileName % {"module_name":self.Name}, self.OutputDir)
  2992. RetVal[AutoFile] = IdfGenBinBuffer.getvalue()
  2993. AutoFile.IsBinary = True
  2994. self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)
  2995. if IdfGenBinBuffer is not None:
  2996. IdfGenBinBuffer.close()
  2997. return RetVal
  2998. ## Return the list of library modules explicitly or implicitly used by this module
  2999. @cached_property
  3000. def DependentLibraryList(self):
  3001. # only merge library classes and PCD for non-library module
  3002. if self.IsLibrary:
  3003. return []
  3004. return self.PlatformInfo.ApplyLibraryInstance(self.Module)
  3005. ## Get the list of PCDs from current module
  3006. #
  3007. # @retval list The list of PCD
  3008. #
  3009. @cached_property
  3010. def ModulePcdList(self):
  3011. # apply PCD settings from platform
  3012. RetVal = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
  3013. ExtendCopyDictionaryLists(self._PcdComments, self.Module.PcdComments)
  3014. return RetVal
  3015. ## Get the list of PCDs from dependent libraries
  3016. #
  3017. # @retval list The list of PCD
  3018. #
  3019. @cached_property
  3020. def LibraryPcdList(self):
  3021. if self.IsLibrary:
  3022. return []
  3023. RetVal = []
  3024. Pcds = set()
  3025. # get PCDs from dependent libraries
  3026. for Library in self.DependentLibraryList:
  3027. PcdsInLibrary = OrderedDict()
  3028. ExtendCopyDictionaryLists(self._PcdComments, Library.PcdComments)
  3029. for Key in Library.Pcds:
  3030. # skip duplicated PCDs
  3031. if Key in self.Module.Pcds or Key in Pcds:
  3032. continue
  3033. Pcds.add(Key)
  3034. PcdsInLibrary[Key] = copy.copy(Library.Pcds[Key])
  3035. RetVal.extend(self.PlatformInfo.ApplyPcdSetting(self.Module, PcdsInLibrary, Library=Library))
  3036. return RetVal
  3037. ## Get the GUID value mapping
  3038. #
  3039. # @retval dict The mapping between GUID cname and its value
  3040. #
  3041. @cached_property
  3042. def GuidList(self):
  3043. RetVal = OrderedDict(self.Module.Guids)
  3044. for Library in self.DependentLibraryList:
  3045. RetVal.update(Library.Guids)
  3046. ExtendCopyDictionaryLists(self._GuidComments, Library.GuidComments)
  3047. ExtendCopyDictionaryLists(self._GuidComments, self.Module.GuidComments)
  3048. return RetVal
  3049. @cached_property
  3050. def GetGuidsUsedByPcd(self):
  3051. RetVal = OrderedDict(self.Module.GetGuidsUsedByPcd())
  3052. for Library in self.DependentLibraryList:
  3053. RetVal.update(Library.GetGuidsUsedByPcd())
  3054. return RetVal
  3055. ## Get the protocol value mapping
  3056. #
  3057. # @retval dict The mapping between protocol cname and its value
  3058. #
  3059. @cached_property
  3060. def ProtocolList(self):
  3061. RetVal = OrderedDict(self.Module.Protocols)
  3062. for Library in self.DependentLibraryList:
  3063. RetVal.update(Library.Protocols)
  3064. ExtendCopyDictionaryLists(self._ProtocolComments, Library.ProtocolComments)
  3065. ExtendCopyDictionaryLists(self._ProtocolComments, self.Module.ProtocolComments)
  3066. return RetVal
  3067. ## Get the PPI value mapping
  3068. #
  3069. # @retval dict The mapping between PPI cname and its value
  3070. #
  3071. @cached_property
  3072. def PpiList(self):
  3073. RetVal = OrderedDict(self.Module.Ppis)
  3074. for Library in self.DependentLibraryList:
  3075. RetVal.update(Library.Ppis)
  3076. ExtendCopyDictionaryLists(self._PpiComments, Library.PpiComments)
  3077. ExtendCopyDictionaryLists(self._PpiComments, self.Module.PpiComments)
  3078. return RetVal
  3079. ## Get the list of include search path
  3080. #
  3081. # @retval list The list path
  3082. #
  3083. @cached_property
  3084. def IncludePathList(self):
  3085. RetVal = []
  3086. RetVal.append(self.MetaFile.Dir)
  3087. RetVal.append(self.DebugDir)
  3088. for Package in self.Module.Packages:
  3089. PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)
  3090. if PackageDir not in RetVal:
  3091. RetVal.append(PackageDir)
  3092. IncludesList = Package.Includes
  3093. if Package._PrivateIncludes:
  3094. if not self.MetaFile.Path.startswith(PackageDir):
  3095. IncludesList = list(set(Package.Includes).difference(set(Package._PrivateIncludes)))
  3096. for Inc in IncludesList:
  3097. if Inc not in RetVal:
  3098. RetVal.append(str(Inc))
  3099. return RetVal
  3100. @cached_property
  3101. def IncludePathLength(self):
  3102. return sum(len(inc)+1 for inc in self.IncludePathList)
  3103. ## Get HII EX PCDs which maybe used by VFR
  3104. #
  3105. # efivarstore used by VFR may relate with HII EX PCDs
  3106. # Get the variable name and GUID from efivarstore and HII EX PCD
  3107. # List the HII EX PCDs in As Built INF if both name and GUID match.
  3108. #
  3109. # @retval list HII EX PCDs
  3110. #
  3111. def _GetPcdsMaybeUsedByVfr(self):
  3112. if not self.SourceFileList:
  3113. return []
  3114. NameGuids = set()
  3115. for SrcFile in self.SourceFileList:
  3116. if SrcFile.Ext.lower() != '.vfr':
  3117. continue
  3118. Vfri = os.path.join(self.OutputDir, SrcFile.BaseName + '.i')
  3119. if not os.path.exists(Vfri):
  3120. continue
  3121. VfriFile = open(Vfri, 'r')
  3122. Content = VfriFile.read()
  3123. VfriFile.close()
  3124. Pos = Content.find('efivarstore')
  3125. while Pos != -1:
  3126. #
  3127. # Make sure 'efivarstore' is the start of efivarstore statement
  3128. # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'
  3129. #
  3130. Index = Pos - 1
  3131. while Index >= 0 and Content[Index] in ' \t\r\n':
  3132. Index -= 1
  3133. if Index >= 0 and Content[Index] != ';':
  3134. Pos = Content.find('efivarstore', Pos + len('efivarstore'))
  3135. continue
  3136. #
  3137. # 'efivarstore' must be followed by name and guid
  3138. #
  3139. Name = gEfiVarStoreNamePattern.search(Content, Pos)
  3140. if not Name:
  3141. break
  3142. Guid = gEfiVarStoreGuidPattern.search(Content, Pos)
  3143. if not Guid:
  3144. break
  3145. NameArray = _ConvertStringToByteArray('L"' + Name.group(1) + '"')
  3146. NameGuids.add((NameArray, GuidStructureStringToGuidString(Guid.group(1))))
  3147. Pos = Content.find('efivarstore', Name.end())
  3148. if not NameGuids:
  3149. return []
  3150. HiiExPcds = []
  3151. for Pcd in self.PlatformInfo.Platform.Pcds.values():
  3152. if Pcd.Type != TAB_PCDS_DYNAMIC_EX_HII:
  3153. continue
  3154. for SkuInfo in Pcd.SkuInfoList.values():
  3155. Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path)
  3156. if not Value:
  3157. continue
  3158. Name = _ConvertStringToByteArray(SkuInfo.VariableName)
  3159. Guid = GuidStructureStringToGuidString(Value)
  3160. if (Name, Guid) in NameGuids and Pcd not in HiiExPcds:
  3161. HiiExPcds.append(Pcd)
  3162. break
  3163. return HiiExPcds
  3164. def _GenOffsetBin(self):
  3165. VfrUniBaseName = {}
  3166. for SourceFile in self.Module.Sources:
  3167. if SourceFile.Type.upper() == ".VFR" :
  3168. #
  3169. # search the .map file to find the offset of vfr binary in the PE32+/TE file.
  3170. #
  3171. VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")
  3172. elif SourceFile.Type.upper() == ".UNI" :
  3173. #
  3174. # search the .map file to find the offset of Uni strings binary in the PE32+/TE file.
  3175. #
  3176. VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")
  3177. if not VfrUniBaseName:
  3178. return None
  3179. MapFileName = os.path.join(self.OutputDir, self.Name + ".map")
  3180. EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")
  3181. VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, list(VfrUniBaseName.values()))
  3182. if not VfrUniOffsetList:
  3183. return None
  3184. OutputName = '%sOffset.bin' % self.Name
  3185. UniVfrOffsetFileName = os.path.join( self.OutputDir, OutputName)
  3186. try:
  3187. fInputfile = open(UniVfrOffsetFileName, "wb+", 0)
  3188. except:
  3189. EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName, None)
  3190. # Use a instance of BytesIO to cache data
  3191. fStringIO = BytesIO()
  3192. for Item in VfrUniOffsetList:
  3193. if (Item[0].find("Strings") != -1):
  3194. #
  3195. # UNI offset in image.
  3196. # GUID + Offset
  3197. # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }
  3198. #
  3199. UniGuid = b'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'
  3200. fStringIO.write(UniGuid)
  3201. UniValue = pack ('Q', int (Item[1], 16))
  3202. fStringIO.write (UniValue)
  3203. else:
  3204. #
  3205. # VFR binary offset in image.
  3206. # GUID + Offset
  3207. # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };
  3208. #
  3209. VfrGuid = b'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'
  3210. fStringIO.write(VfrGuid)
  3211. VfrValue = pack ('Q', int (Item[1], 16))
  3212. fStringIO.write (VfrValue)
  3213. #
  3214. # write data into file.
  3215. #
  3216. try :
  3217. fInputfile.write (fStringIO.getvalue())
  3218. except:
  3219. EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "
  3220. "file been locked or using by other applications." %UniVfrOffsetFileName, None)
  3221. fStringIO.close ()
  3222. fInputfile.close ()
  3223. return OutputName
  3224. ## Create AsBuilt INF file the module
  3225. #
  3226. def CreateAsBuiltInf(self, IsOnlyCopy = False):
  3227. self.OutputFile = set()
  3228. if IsOnlyCopy and GlobalData.gBinCacheDest:
  3229. self.CopyModuleToCache()
  3230. return
  3231. if self.IsAsBuiltInfCreated:
  3232. return
  3233. # Skip the following code for libraries
  3234. if self.IsLibrary:
  3235. return
  3236. # Skip the following code for modules with no source files
  3237. if not self.SourceFileList:
  3238. return
  3239. # Skip the following code for modules without any binary files
  3240. if self.BinaryFileList:
  3241. return
  3242. ### TODO: How to handles mixed source and binary modules
  3243. # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries
  3244. # Also find all packages that the DynamicEx PCDs depend on
  3245. Pcds = []
  3246. PatchablePcds = []
  3247. Packages = []
  3248. PcdCheckList = []
  3249. PcdTokenSpaceList = []
  3250. for Pcd in self.ModulePcdList + self.LibraryPcdList:
  3251. if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE:
  3252. PatchablePcds.append(Pcd)
  3253. PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_PATCHABLE_IN_MODULE))
  3254. elif Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:
  3255. if Pcd not in Pcds:
  3256. Pcds.append(Pcd)
  3257. PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC_EX))
  3258. PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC))
  3259. PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)
  3260. GuidList = OrderedDict(self.GuidList)
  3261. for TokenSpace in self.GetGuidsUsedByPcd:
  3262. # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list
  3263. # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs
  3264. if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList:
  3265. GuidList.pop(TokenSpace)
  3266. CheckList = (GuidList, self.PpiList, self.ProtocolList, PcdCheckList)
  3267. for Package in self.DerivedPackageList:
  3268. if Package in Packages:
  3269. continue
  3270. BeChecked = (Package.Guids, Package.Ppis, Package.Protocols, Package.Pcds)
  3271. Found = False
  3272. for Index in range(len(BeChecked)):
  3273. for Item in CheckList[Index]:
  3274. if Item in BeChecked[Index]:
  3275. Packages.append(Package)
  3276. Found = True
  3277. break
  3278. if Found:
  3279. break
  3280. VfrPcds = self._GetPcdsMaybeUsedByVfr()
  3281. for Pkg in self.PlatformInfo.PackageList:
  3282. if Pkg in Packages:
  3283. continue
  3284. for VfrPcd in VfrPcds:
  3285. if ((VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC_EX) in Pkg.Pcds or
  3286. (VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, TAB_PCDS_DYNAMIC) in Pkg.Pcds):
  3287. Packages.append(Pkg)
  3288. break
  3289. ModuleType = SUP_MODULE_DXE_DRIVER if self.ModuleType == SUP_MODULE_UEFI_DRIVER and self.DepexGenerated else self.ModuleType
  3290. DriverType = self.PcdIsDriver if self.PcdIsDriver else ''
  3291. Guid = self.Guid
  3292. MDefs = self.Module.Defines
  3293. AsBuiltInfDict = {
  3294. 'module_name' : self.Name,
  3295. 'module_guid' : Guid,
  3296. 'module_module_type' : ModuleType,
  3297. 'module_version_string' : [MDefs['VERSION_STRING']] if 'VERSION_STRING' in MDefs else [],
  3298. 'pcd_is_driver_string' : [],
  3299. 'module_uefi_specification_version' : [],
  3300. 'module_pi_specification_version' : [],
  3301. 'module_entry_point' : self.Module.ModuleEntryPointList,
  3302. 'module_unload_image' : self.Module.ModuleUnloadImageList,
  3303. 'module_constructor' : self.Module.ConstructorList,
  3304. 'module_destructor' : self.Module.DestructorList,
  3305. 'module_shadow' : [MDefs['SHADOW']] if 'SHADOW' in MDefs else [],
  3306. 'module_pci_vendor_id' : [MDefs['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs else [],
  3307. 'module_pci_device_id' : [MDefs['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs else [],
  3308. 'module_pci_class_code' : [MDefs['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs else [],
  3309. 'module_pci_revision' : [MDefs['PCI_REVISION']] if 'PCI_REVISION' in MDefs else [],
  3310. 'module_build_number' : [MDefs['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs else [],
  3311. 'module_spec' : [MDefs['SPEC']] if 'SPEC' in MDefs else [],
  3312. 'module_uefi_hii_resource_section' : [MDefs['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs else [],
  3313. 'module_uni_file' : [MDefs['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs else [],
  3314. 'module_arch' : self.Arch,
  3315. 'package_item' : [Package.MetaFile.File.replace('\\', '/') for Package in Packages],
  3316. 'binary_item' : [],
  3317. 'patchablepcd_item' : [],
  3318. 'pcd_item' : [],
  3319. 'protocol_item' : [],
  3320. 'ppi_item' : [],
  3321. 'guid_item' : [],
  3322. 'flags_item' : [],
  3323. 'libraryclasses_item' : []
  3324. }
  3325. if 'MODULE_UNI_FILE' in MDefs:
  3326. UNIFile = os.path.join(self.MetaFile.Dir, MDefs['MODULE_UNI_FILE'])
  3327. if os.path.isfile(UNIFile):
  3328. shutil.copy2(UNIFile, self.OutputDir)
  3329. if self.AutoGenVersion > int(gInfSpecVersion, 0):
  3330. AsBuiltInfDict['module_inf_version'] = '0x%08x' % self.AutoGenVersion
  3331. else:
  3332. AsBuiltInfDict['module_inf_version'] = gInfSpecVersion
  3333. if DriverType:
  3334. AsBuiltInfDict['pcd_is_driver_string'].append(DriverType)
  3335. if 'UEFI_SPECIFICATION_VERSION' in self.Specification:
  3336. AsBuiltInfDict['module_uefi_specification_version'].append(self.Specification['UEFI_SPECIFICATION_VERSION'])
  3337. if 'PI_SPECIFICATION_VERSION' in self.Specification:
  3338. AsBuiltInfDict['module_pi_specification_version'].append(self.Specification['PI_SPECIFICATION_VERSION'])
  3339. OutputDir = self.OutputDir.replace('\\', '/').strip('/')
  3340. DebugDir = self.DebugDir.replace('\\', '/').strip('/')
  3341. for Item in self.CodaTargetList:
  3342. File = Item.Target.Path.replace('\\', '/').strip('/').replace(DebugDir, '').replace(OutputDir, '').strip('/')
  3343. self.OutputFile.add(File)
  3344. if os.path.isabs(File):
  3345. File = File.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')
  3346. if Item.Target.Ext.lower() == '.aml':
  3347. AsBuiltInfDict['binary_item'].append('ASL|' + File)
  3348. elif Item.Target.Ext.lower() == '.acpi':
  3349. AsBuiltInfDict['binary_item'].append('ACPI|' + File)
  3350. elif Item.Target.Ext.lower() == '.efi':
  3351. AsBuiltInfDict['binary_item'].append('PE32|' + self.Name + '.efi')
  3352. else:
  3353. AsBuiltInfDict['binary_item'].append('BIN|' + File)
  3354. if not self.DepexGenerated:
  3355. DepexFile = os.path.join(self.OutputDir, self.Name + '.depex')
  3356. if os.path.exists(DepexFile):
  3357. self.DepexGenerated = True
  3358. if self.DepexGenerated:
  3359. self.OutputFile.add(self.Name + '.depex')
  3360. if self.ModuleType in [SUP_MODULE_PEIM]:
  3361. AsBuiltInfDict['binary_item'].append('PEI_DEPEX|' + self.Name + '.depex')
  3362. elif self.ModuleType in [SUP_MODULE_DXE_DRIVER, SUP_MODULE_DXE_RUNTIME_DRIVER, SUP_MODULE_DXE_SAL_DRIVER, SUP_MODULE_UEFI_DRIVER]:
  3363. AsBuiltInfDict['binary_item'].append('DXE_DEPEX|' + self.Name + '.depex')
  3364. elif self.ModuleType in [SUP_MODULE_DXE_SMM_DRIVER]:
  3365. AsBuiltInfDict['binary_item'].append('SMM_DEPEX|' + self.Name + '.depex')
  3366. Bin = self._GenOffsetBin()
  3367. if Bin:
  3368. AsBuiltInfDict['binary_item'].append('BIN|%s' % Bin)
  3369. self.OutputFile.add(Bin)
  3370. for Root, Dirs, Files in os.walk(OutputDir):
  3371. for File in Files:
  3372. if File.lower().endswith('.pdb'):
  3373. AsBuiltInfDict['binary_item'].append('DISPOSABLE|' + File)
  3374. self.OutputFile.add(File)
  3375. HeaderComments = self.Module.HeaderComments
  3376. StartPos = 0
  3377. for Index in range(len(HeaderComments)):
  3378. if HeaderComments[Index].find('@BinaryHeader') != -1:
  3379. HeaderComments[Index] = HeaderComments[Index].replace('@BinaryHeader', '@file')
  3380. StartPos = Index
  3381. break
  3382. AsBuiltInfDict['header_comments'] = '\n'.join(HeaderComments[StartPos:]).replace(':#', '://')
  3383. AsBuiltInfDict['tail_comments'] = '\n'.join(self.Module.TailComments)
  3384. GenList = [
  3385. (self.ProtocolList, self._ProtocolComments, 'protocol_item'),
  3386. (self.PpiList, self._PpiComments, 'ppi_item'),
  3387. (GuidList, self._GuidComments, 'guid_item')
  3388. ]
  3389. for Item in GenList:
  3390. for CName in Item[0]:
  3391. Comments = '\n '.join(Item[1][CName]) if CName in Item[1] else ''
  3392. Entry = Comments + '\n ' + CName if Comments else CName
  3393. AsBuiltInfDict[Item[2]].append(Entry)
  3394. PatchList = parsePcdInfoFromMapFile(
  3395. os.path.join(self.OutputDir, self.Name + '.map'),
  3396. os.path.join(self.OutputDir, self.Name + '.efi')
  3397. )
  3398. if PatchList:
  3399. for Pcd in PatchablePcds:
  3400. TokenCName = Pcd.TokenCName
  3401. for PcdItem in GlobalData.MixedPcd:
  3402. if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
  3403. TokenCName = PcdItem[0]
  3404. break
  3405. for PatchPcd in PatchList:
  3406. if TokenCName == PatchPcd[0]:
  3407. break
  3408. else:
  3409. continue
  3410. PcdValue = ''
  3411. if Pcd.DatumType == 'BOOLEAN':
  3412. BoolValue = Pcd.DefaultValue.upper()
  3413. if BoolValue == 'TRUE':
  3414. Pcd.DefaultValue = '1'
  3415. elif BoolValue == 'FALSE':
  3416. Pcd.DefaultValue = '0'
  3417. if Pcd.DatumType in TAB_PCD_NUMERIC_TYPES:
  3418. HexFormat = '0x%02x'
  3419. if Pcd.DatumType == TAB_UINT16:
  3420. HexFormat = '0x%04x'
  3421. elif Pcd.DatumType == TAB_UINT32:
  3422. HexFormat = '0x%08x'
  3423. elif Pcd.DatumType == TAB_UINT64:
  3424. HexFormat = '0x%016x'
  3425. PcdValue = HexFormat % int(Pcd.DefaultValue, 0)
  3426. else:
  3427. if Pcd.MaxDatumSize is None or Pcd.MaxDatumSize == '':
  3428. EdkLogger.error("build", AUTOGEN_ERROR,
  3429. "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, TokenCName)
  3430. )
  3431. ArraySize = int(Pcd.MaxDatumSize, 0)
  3432. PcdValue = Pcd.DefaultValue
  3433. if PcdValue[0] != '{':
  3434. Unicode = False
  3435. if PcdValue[0] == 'L':
  3436. Unicode = True
  3437. PcdValue = PcdValue.lstrip('L')
  3438. PcdValue = eval(PcdValue)
  3439. NewValue = '{'
  3440. for Index in range(0, len(PcdValue)):
  3441. if Unicode:
  3442. CharVal = ord(PcdValue[Index])
  3443. NewValue = NewValue + '0x%02x' % (CharVal & 0x00FF) + ', ' \
  3444. + '0x%02x' % (CharVal >> 8) + ', '
  3445. else:
  3446. NewValue = NewValue + '0x%02x' % (ord(PcdValue[Index]) % 0x100) + ', '
  3447. Padding = '0x00, '
  3448. if Unicode:
  3449. Padding = Padding * 2
  3450. ArraySize = ArraySize // 2
  3451. if ArraySize < (len(PcdValue) + 1):
  3452. if Pcd.MaxSizeUserSet:
  3453. EdkLogger.error("build", AUTOGEN_ERROR,
  3454. "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
  3455. )
  3456. else:
  3457. ArraySize = len(PcdValue) + 1
  3458. if ArraySize > len(PcdValue) + 1:
  3459. NewValue = NewValue + Padding * (ArraySize - len(PcdValue) - 1)
  3460. PcdValue = NewValue + Padding.strip().rstrip(',') + '}'
  3461. elif len(PcdValue.split(',')) <= ArraySize:
  3462. PcdValue = PcdValue.rstrip('}') + ', 0x00' * (ArraySize - len(PcdValue.split(',')))
  3463. PcdValue += '}'
  3464. else:
  3465. if Pcd.MaxSizeUserSet:
  3466. EdkLogger.error("build", AUTOGEN_ERROR,
  3467. "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)
  3468. )
  3469. else:
  3470. ArraySize = len(PcdValue) + 1
  3471. PcdItem = '%s.%s|%s|0x%X' % \
  3472. (Pcd.TokenSpaceGuidCName, TokenCName, PcdValue, PatchPcd[1])
  3473. PcdComments = ''
  3474. if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
  3475. PcdComments = '\n '.join(self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName])
  3476. if PcdComments:
  3477. PcdItem = PcdComments + '\n ' + PcdItem
  3478. AsBuiltInfDict['patchablepcd_item'].append(PcdItem)
  3479. for Pcd in Pcds + VfrPcds:
  3480. PcdCommentList = []
  3481. HiiInfo = ''
  3482. TokenCName = Pcd.TokenCName
  3483. for PcdItem in GlobalData.MixedPcd:
  3484. if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:
  3485. TokenCName = PcdItem[0]
  3486. break
  3487. if Pcd.Type == TAB_PCDS_DYNAMIC_EX_HII:
  3488. for SkuName in Pcd.SkuInfoList:
  3489. SkuInfo = Pcd.SkuInfoList[SkuName]
  3490. HiiInfo = '## %s|%s|%s' % (SkuInfo.VariableName, SkuInfo.VariableGuid, SkuInfo.VariableOffset)
  3491. break
  3492. if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:
  3493. PcdCommentList = self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName][:]
  3494. if HiiInfo:
  3495. UsageIndex = -1
  3496. UsageStr = ''
  3497. for Index, Comment in enumerate(PcdCommentList):
  3498. for Usage in UsageList:
  3499. if Comment.find(Usage) != -1:
  3500. UsageStr = Usage
  3501. UsageIndex = Index
  3502. break
  3503. if UsageIndex != -1:
  3504. PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, ''))
  3505. else:
  3506. PcdCommentList.append('## UNDEFINED ' + HiiInfo)
  3507. PcdComments = '\n '.join(PcdCommentList)
  3508. PcdEntry = Pcd.TokenSpaceGuidCName + '.' + TokenCName
  3509. if PcdComments:
  3510. PcdEntry = PcdComments + '\n ' + PcdEntry
  3511. AsBuiltInfDict['pcd_item'].append(PcdEntry)
  3512. for Item in self.BuildOption:
  3513. if 'FLAGS' in self.BuildOption[Item]:
  3514. AsBuiltInfDict['flags_item'].append('%s:%s_%s_%s_%s_FLAGS = %s' % (self.ToolChainFamily, self.BuildTarget, self.ToolChain, self.Arch, Item, self.BuildOption[Item]['FLAGS'].strip()))
  3515. # Generated LibraryClasses section in comments.
  3516. for Library in self.LibraryAutoGenList:
  3517. AsBuiltInfDict['libraryclasses_item'].append(Library.MetaFile.File.replace('\\', '/'))
  3518. # Generated UserExtensions TianoCore section.
  3519. # All tianocore user extensions are copied.
  3520. UserExtStr = ''
  3521. for TianoCore in self._GetTianoCoreUserExtensionList():
  3522. UserExtStr += '\n'.join(TianoCore)
  3523. ExtensionFile = os.path.join(self.MetaFile.Dir, TianoCore[1])
  3524. if os.path.isfile(ExtensionFile):
  3525. shutil.copy2(ExtensionFile, self.OutputDir)
  3526. AsBuiltInfDict['userextension_tianocore_item'] = UserExtStr
  3527. # Generated depex expression section in comments.
  3528. DepexExpression = self._GetDepexExpresionString()
  3529. AsBuiltInfDict['depexsection_item'] = DepexExpression if DepexExpression else ''
  3530. AsBuiltInf = TemplateString()
  3531. AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))
  3532. SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)
  3533. self.IsAsBuiltInfCreated = True
  3534. if GlobalData.gBinCacheDest:
  3535. self.CopyModuleToCache()
  3536. def CopyModuleToCache(self):
  3537. FileDir = path.join(GlobalData.gBinCacheDest, self.Arch, self.SourceDir, self.MetaFile.BaseName)
  3538. CreateDirectory (FileDir)
  3539. HashFile = path.join(self.BuildDir, self.Name + '.hash')
  3540. ModuleFile = path.join(self.OutputDir, self.Name + '.inf')
  3541. if os.path.exists(HashFile):
  3542. shutil.copy2(HashFile, FileDir)
  3543. if os.path.exists(ModuleFile):
  3544. shutil.copy2(ModuleFile, FileDir)
  3545. if not self.OutputFile:
  3546. Ma = self.BuildDatabase[PathClass(ModuleFile), self.Arch, self.BuildTarget, self.ToolChain]
  3547. self.OutputFile = Ma.Binaries
  3548. if self.OutputFile:
  3549. for File in self.OutputFile:
  3550. File = str(File)
  3551. if not os.path.isabs(File):
  3552. File = os.path.join(self.OutputDir, File)
  3553. if os.path.exists(File):
  3554. shutil.copy2(File, FileDir)
  3555. def AttemptModuleCacheCopy(self):
  3556. if self.IsBinaryModule:
  3557. return False
  3558. FileDir = path.join(GlobalData.gBinCacheSource, self.Arch, self.SourceDir, self.MetaFile.BaseName)
  3559. HashFile = path.join(FileDir, self.Name + '.hash')
  3560. if os.path.exists(HashFile):
  3561. f = open(HashFile, 'r')
  3562. CacheHash = f.read()
  3563. f.close()
  3564. if GlobalData.gModuleHash[self.Arch][self.Name]:
  3565. if CacheHash == GlobalData.gModuleHash[self.Arch][self.Name]:
  3566. for root, dir, files in os.walk(FileDir):
  3567. for f in files:
  3568. if self.Name + '.hash' in f:
  3569. shutil.copy2(HashFile, self.BuildDir)
  3570. else:
  3571. File = path.join(root, f)
  3572. shutil.copy2(File, self.OutputDir)
  3573. if self.Name == "PcdPeim" or self.Name == "PcdDxe":
  3574. CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
  3575. return True
  3576. return False
  3577. ## Create makefile for the module and its dependent libraries
  3578. #
  3579. # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of
  3580. # dependent libraries will be created
  3581. #
  3582. @cached_class_function
  3583. def CreateMakeFile(self, CreateLibraryMakeFile=True, GenFfsList = []):
  3584. # nest this function inside it's only caller.
  3585. def CreateTimeStamp():
  3586. FileSet = {self.MetaFile.Path}
  3587. for SourceFile in self.Module.Sources:
  3588. FileSet.add (SourceFile.Path)
  3589. for Lib in self.DependentLibraryList:
  3590. FileSet.add (Lib.MetaFile.Path)
  3591. for f in self.AutoGenDepSet:
  3592. FileSet.add (f.Path)
  3593. if os.path.exists (self.TimeStampPath):
  3594. os.remove (self.TimeStampPath)
  3595. with open(self.TimeStampPath, 'w+') as file:
  3596. for f in FileSet:
  3597. print(f, file=file)
  3598. # Ignore generating makefile when it is a binary module
  3599. if self.IsBinaryModule:
  3600. return
  3601. self.GenFfsList = GenFfsList
  3602. if not self.IsLibrary and CreateLibraryMakeFile:
  3603. for LibraryAutoGen in self.LibraryAutoGenList:
  3604. LibraryAutoGen.CreateMakeFile()
  3605. if self.CanSkip():
  3606. return
  3607. if len(self.CustomMakefile) == 0:
  3608. Makefile = GenMake.ModuleMakefile(self)
  3609. else:
  3610. Makefile = GenMake.CustomMakefile(self)
  3611. if Makefile.Generate():
  3612. EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %
  3613. (self.Name, self.Arch))
  3614. else:
  3615. EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %
  3616. (self.Name, self.Arch))
  3617. CreateTimeStamp()
  3618. def CopyBinaryFiles(self):
  3619. for File in self.Module.Binaries:
  3620. SrcPath = File.Path
  3621. DstPath = os.path.join(self.OutputDir, os.path.basename(SrcPath))
  3622. CopyLongFilePath(SrcPath, DstPath)
  3623. ## Create autogen code for the module and its dependent libraries
  3624. #
  3625. # @param CreateLibraryCodeFile Flag indicating if or not the code of
  3626. # dependent libraries will be created
  3627. #
  3628. def CreateCodeFile(self, CreateLibraryCodeFile=True):
  3629. if self.IsCodeFileCreated:
  3630. return
  3631. # Need to generate PcdDatabase even PcdDriver is binarymodule
  3632. if self.IsBinaryModule and self.PcdIsDriver != '':
  3633. CreatePcdDatabaseCode(self, TemplateString(), TemplateString())
  3634. return
  3635. if self.IsBinaryModule:
  3636. if self.IsLibrary:
  3637. self.CopyBinaryFiles()
  3638. return
  3639. if not self.IsLibrary and CreateLibraryCodeFile:
  3640. for LibraryAutoGen in self.LibraryAutoGenList:
  3641. LibraryAutoGen.CreateCodeFile()
  3642. if self.CanSkip():
  3643. return
  3644. AutoGenList = []
  3645. IgoredAutoGenList = []
  3646. for File in self.AutoGenFileList:
  3647. if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):
  3648. AutoGenList.append(str(File))
  3649. else:
  3650. IgoredAutoGenList.append(str(File))
  3651. for ModuleType in self.DepexList:
  3652. # Ignore empty [depex] section or [depex] section for SUP_MODULE_USER_DEFINED module
  3653. if len(self.DepexList[ModuleType]) == 0 or ModuleType == SUP_MODULE_USER_DEFINED:
  3654. continue
  3655. Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)
  3656. DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}
  3657. if len(Dpx.PostfixNotation) != 0:
  3658. self.DepexGenerated = True
  3659. if Dpx.Generate(path.join(self.OutputDir, DpxFile)):
  3660. AutoGenList.append(str(DpxFile))
  3661. else:
  3662. IgoredAutoGenList.append(str(DpxFile))
  3663. if IgoredAutoGenList == []:
  3664. EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %
  3665. (" ".join(AutoGenList), self.Name, self.Arch))
  3666. elif AutoGenList == []:
  3667. EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %
  3668. (" ".join(IgoredAutoGenList), self.Name, self.Arch))
  3669. else:
  3670. EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %
  3671. (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))
  3672. self.IsCodeFileCreated = True
  3673. return AutoGenList
  3674. ## Summarize the ModuleAutoGen objects of all libraries used by this module
  3675. @cached_property
  3676. def LibraryAutoGenList(self):
  3677. RetVal = []
  3678. for Library in self.DependentLibraryList:
  3679. La = ModuleAutoGen(
  3680. self.Workspace,
  3681. Library.MetaFile,
  3682. self.BuildTarget,
  3683. self.ToolChain,
  3684. self.Arch,
  3685. self.PlatformInfo.MetaFile
  3686. )
  3687. if La not in RetVal:
  3688. RetVal.append(La)
  3689. for Lib in La.CodaTargetList:
  3690. self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)
  3691. return RetVal
  3692. def GenModuleHash(self):
  3693. if self.Arch not in GlobalData.gModuleHash:
  3694. GlobalData.gModuleHash[self.Arch] = {}
  3695. m = hashlib.md5()
  3696. # Add Platform level hash
  3697. m.update(GlobalData.gPlatformHash.encode('utf-8'))
  3698. # Add Package level hash
  3699. if self.DependentPackageList:
  3700. for Pkg in sorted(self.DependentPackageList, key=lambda x: x.PackageName):
  3701. if Pkg.PackageName in GlobalData.gPackageHash[self.Arch]:
  3702. m.update(GlobalData.gPackageHash[self.Arch][Pkg.PackageName].encode('utf-8'))
  3703. # Add Library hash
  3704. if self.LibraryAutoGenList:
  3705. for Lib in sorted(self.LibraryAutoGenList, key=lambda x: x.Name):
  3706. if Lib.Name not in GlobalData.gModuleHash[self.Arch]:
  3707. Lib.GenModuleHash()
  3708. m.update(GlobalData.gModuleHash[self.Arch][Lib.Name].encode('utf-8'))
  3709. # Add Module self
  3710. f = open(str(self.MetaFile), 'rb')
  3711. Content = f.read()
  3712. f.close()
  3713. m.update(Content)
  3714. # Add Module's source files
  3715. if self.SourceFileList:
  3716. for File in sorted(self.SourceFileList, key=lambda x: str(x)):
  3717. f = open(str(File), 'rb')
  3718. Content = f.read()
  3719. f.close()
  3720. m.update(Content)
  3721. ModuleHashFile = path.join(self.BuildDir, self.Name + ".hash")
  3722. if self.Name not in GlobalData.gModuleHash[self.Arch]:
  3723. GlobalData.gModuleHash[self.Arch][self.Name] = m.hexdigest()
  3724. if GlobalData.gBinCacheSource:
  3725. if self.AttemptModuleCacheCopy():
  3726. return False
  3727. return SaveFileOnChange(ModuleHashFile, m.hexdigest(), False)
  3728. ## Decide whether we can skip the ModuleAutoGen process
  3729. def CanSkipbyHash(self):
  3730. if GlobalData.gUseHashCache:
  3731. return not self.GenModuleHash()
  3732. return False
  3733. ## Decide whether we can skip the ModuleAutoGen process
  3734. # If any source file is newer than the module than we cannot skip
  3735. #
  3736. def CanSkip(self):
  3737. if self.MakeFileDir in GlobalData.gSikpAutoGenCache:
  3738. return True
  3739. if not os.path.exists(self.TimeStampPath):
  3740. return False
  3741. #last creation time of the module
  3742. DstTimeStamp = os.stat(self.TimeStampPath)[8]
  3743. SrcTimeStamp = self.Workspace._SrcTimeStamp
  3744. if SrcTimeStamp > DstTimeStamp:
  3745. return False
  3746. with open(self.TimeStampPath,'r') as f:
  3747. for source in f:
  3748. source = source.rstrip('\n')
  3749. if not os.path.exists(source):
  3750. return False
  3751. if source not in ModuleAutoGen.TimeDict :
  3752. ModuleAutoGen.TimeDict[source] = os.stat(source)[8]
  3753. if ModuleAutoGen.TimeDict[source] > DstTimeStamp:
  3754. return False
  3755. GlobalData.gSikpAutoGenCache.add(self.MakeFileDir)
  3756. return True
  3757. @cached_property
  3758. def TimeStampPath(self):
  3759. return os.path.join(self.MakeFileDir, 'AutoGenTimeStamp')