/* Ċ Ġ* ĠCopyright Ġ 2 0 1 0 - 2 0 1 9 ĠJetBrains Ġs . r . o . ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense Ċ Ġ* Ġthat Ġcan Ġbe Ġfound Ġin Ġthe ĠLICENSE Ġfile . Ċ Ġ*/ Ċ Ċ package Ġorg . jetbrains . kotlin . cli . utilities Ċ Ċ import Ġorg . jetbrains . kotlin . cli . bc . K 2 Native Ċ import Ġorg . jetbrains . kotlin . kon an . file . File Ċ import Ġjava . util . concurrent .* Ċ import Ġkotlinx . cli .* Ċ Ċ fun Ġgenerate Platform Libraries ( args : ĠArray < String >) Ġ{ ĊĠĠĠ Ġval Ġarg Parser Ġ= ĠArg Parser (" generate - platform ", Ġprefix Style Ġ= ĠArg Parser . OPTION _ PREFIX _ STYLE . JVM ) ĊĠĠĠ Ġval Ġinput DirectoryPath Ġby Ġarg Parser . option ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠArg Type . String , Ġ" input - directory ", Ġ" i ", Ġ" Input Ġdirectory "). required () ĊĠĠĠ Ġval Ġoutput DirectoryPath Ġby Ġarg Parser . option ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠArg Type . String , Ġ" output - directory ", Ġ" o ", Ġ" Output Ġdirectory "). required () ĊĠĠĠ Ġval Ġtarget Ġby Ġarg Parser . option ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠArg Type . String , Ġ" target ", Ġ" t ", Ġ" Compilation Ġtarget "). required () ĊĠĠĠ Ġval Ġsave Temp s Ġby Ġarg Parser . option ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠArg Type . Boolean , Ġ" save - temp s ", Ġ" s ", Ġ" Save Ġtemporary Ġfiles "). default ( false ) ĊĠĠĠ Ġarg Parser . parse ( args ) ĊĊĠĠĠ Ġval Ġinput Directory Ġ= ĠFile ( input DirectoryPath ) ĊĠĠĠ Ġval Ġoutput Directory Ġ= ĠFile ( output DirectoryPath ) ĊĊĠĠĠ Ġif Ġ(! input Directory . exists ) Ġthrow ĠError (" input Ġdirectory Ġdoesn 't Ġexist ") ĊĠĠĠ Ġif Ġ(! output Directory . exists ) Ġ{ ĊĠĠĠĠĠĠĠ Ġoutput Directory . mkdir s () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġgenerate Platform Libraries ( target , Ġinput Directory , Ġoutput Directory , Ġsave Temp s ) Ċ } Ċ Ċ private Ġclass ĠDef File ( val Ġname : ĠString , Ġval Ġdepends : ĠMutable List < Def File >) Ġ{ ĊĠĠĠ Ġoverride Ġfun ĠtoString (): ĠString Ġ= Ġ"$ name : Ġ[ ${ depends . join ToString ( separator Ġ= Ġ", Ġ") Ġ{ Ġit . name Ġ}} ]" Ċ } Ċ Ċ private Ġfun Ġtopo Sort ( def Files : ĠList < Def File >): ĠList < Def File > Ġ{ ĊĠĠĠ Ġ// ĠDo ĠDFS Ġto pos ort . ĊĠĠĠ Ġval Ġmark Gray Ġ= Ġmutable Set Of < Def File >() ĊĠĠĠ Ġval Ġmark Black Ġ= Ġmutable Set Of < Def File >() ĊĠĠĠ Ġval Ġresult Ġ= Ġmutable ListOf < Def File >() ĊĊĠĠĠ Ġfun Ġvisit ( def : ĠDef File ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( mark Black . contains ( def )) Ġreturn ĊĠĠĠĠĠĠĠ Ġif Ġ( mark Gray . contains ( def )) Ġthrow ĠError ("$ def Ġis Ġpart Ġof Ġcycle ") ĊĠĠĠĠĠĠĠ Ġmark Gray Ġ+= Ġdef ĊĠĠĠĠĠĠĠ Ġdef . depends . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvisit ( it ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġmark Gray Ġ-= Ġdef ĊĠĠĠĠĠĠĠ Ġmark Black Ġ+= Ġdef ĊĠĠĠĠĠĠĠ Ġresult Ġ+= Ġdef ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġvar Ġindex Ġ= Ġ 0 ĊĠĠĠ Ġwhile Ġ( mark Black . size Ġ< Ġdef Files . size ) Ġ{ ĊĠĠĠĠĠĠĠ Ġvisit ( def Files [ index ++ ]) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġresult Ċ } Ċ Ċ private Ġfun Ġgenerate Platform Libraries ( target : ĠString , Ġinput Directory : ĠFile , Ġoutput Directory : ĠFile , Ġsave Temp s : ĠBoolean ) Ġ{ ĊĠĠĠ Ġfun Ġbuild K lib ( def : ĠDef File ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfile Ġ= ĠFile ("$ input Directory /${ def . name }. def ") ĊĠĠĠĠĠĠĠ ĠFile ("${ output Directory . absolute Path }/ build -${ def . name } "). mkdir s () ĊĠĠĠĠĠĠĠ Ġval Ġout K lib Ġ= Ġ"${ output Directory . absolute Path }/ build -${ def . name }/${ def . name }. k lib " ĊĠĠĠĠĠĠĠ Ġval Ġargs Ġ= ĠarrayOf ("- o ", Ġout K lib , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"- target ", Ġtarget , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"- def ", Ġfile . absolute Path , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"- compiler - option ", Ġ"- f modules - cache - path =$ output Directory / clang Modules Cache ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"- repo ", Ġ Ġ"${ output Directory . absolute Path }", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"- no - default - libs ", Ġ"- no - endor sed - libs ", Ġ"- X purge - user - libs ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ* def . depends . flatMap Ġ{ ĠlistOf ("- l ", Ġ"$ output Directory /${ it . name }") Ġ}. to Typed Array ()) ĊĠĠĠĠĠĠĠ Ġprintln (" Processing Ġ${ def . name } ...") ĊĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinvoke Interop (" native ", Ġargs )?. let Ġ{ ĠK 2 Native . main No Exit ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġorg . jetbrains . kotlin . cli . k lib . main ( array Of (" install ", Ġout K lib , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"- target ", Ġtarget , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ"- repository ", Ġ"${ output Directory . absolute Path }" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ)) ĊĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! save Temp s ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠFile ("$ output Directory / build -${ def . name } "). delete Re cursively () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġprintln (" generate Ġplatform Ġlibraries Ġfrom Ġ$ input Directory Ġto Ġ$ output Directory Ġfor Ġ$ target ") ĊĠĠĠ Ġ// ĠBuild Ġdependencies Ġgraph . ĊĠĠĠ Ġval Ġdef Files Ġ= Ġmutable Map Of < String , ĠDef File >() ĊĠĠĠ Ġval Ġdepends Regex Ġ= ĠRegex ("^ depends Ġ= Ġ( .* )") ĊĠĠĠ Ġinput Directory . list Files OrEmpty . filter Ġ{ Ġit . extension Ġ== Ġ" def " Ġ}. forEach Ġ{ Ġfile Ġ-> ĊĠĠĠĠĠĠĠ Ġval Ġname Ġ= Ġfile . name . split (". "). also Ġ{ Ġassert ( it . size Ġ== Ġ 2 ) Ġ} [ 0 ] ĊĠĠĠĠĠĠĠ Ġval Ġdef Ġ= Ġdef Files . get Or Put ( name ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠDef File ( name , Ġmutable ListOf ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġfile . forEach Line Ġ{ Ġline Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmatch Ġ= Ġdepends Regex . match Ent ire ( line ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( match Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmatch . group Values [ 1 ]. split (" Ġ"). forEach Ġ{ Ġdependency Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdef . depends . add ( def Files . get Or Put ( dependency ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDef File ( dependency , Ġmutable ListOf ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġval Ġsorted Ġ= Ġtopo Sort ( def Files . values . toList ()) ĊĠĠĠ Ġval Ġnum Co res Ġ= ĠRuntime . get Runtime (). available Processors () ĊĠĠĠ Ġval Ġexecutor Pool Ġ= ĠThreadPool Executor ( num Co res , Ġnum Co res , ĊĠĠĠĠĠĠĠĠĠĠĠĠ 1 0 , ĠTimeUnit . SECONDS , ĠArray BlockingQueue ( 1 0 0 0 ), ĊĠĠĠĠĠĠĠĠĠĠĠ ĠExec utors . default Thread Factory (), ĠReject ed Execution Handler Ġ{ Ġr , Ġ_ Ġ-> ĊĠĠĠĠĠĠĠ Ġprintln (" Execution Ġrejected : Ġ$ r ") ĊĠĠĠĠĠĠĠ Ġthrow ĠError (" Must Ġnot Ġhappen !") ĊĠĠĠ Ġ}) ĊĠĠĠ Ġval Ġbuilt Ġ= ĠConcurrent HashMap ( sorted . associate With Ġ{ Ġ 0 Ġ}) ĊĠĠĠ Ġ// ĠNow Ġrun Ġinter op Ġtool Ġon Ġto pos orted Ġdependencies . ĊĠĠĠ Ġsorted . forEach Ġ{ Ġdef Ġ-> ĊĠĠĠĠĠĠĠ Ġexecutor Pool . execute Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠA Ġbit Ġugly , Ġwe Ġjust Ġblock Ġhere Ġuntil Ġall Ġdependencies Ġare Ġbuilt . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( def . depends . any Ġ{ Ġbuilt [ it ] Ġ== Ġ 0 Ġ}) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠThread . sleep ( 1 0 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( def . depends . any Ġ{ Ġbuilt [ it ] Ġ== Ġ 2 Ġ}) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠError (" There Ġare Ġfailed Ġdependencies Ġfor Ġ$ def ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuild K lib ( def ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuilt [ def ] Ġ= Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch ( e : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuilt [ def ] Ġ= Ġ 2 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow Ġe ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġexecutor Pool . shutdown () ĊĠĠĠ Ġif Ġ(! save Temp s ) Ġ{ ĊĠĠĠĠĠĠĠ ĠFile ("$ output Directory / clang Modules Cache "). delete Re cursively () ĊĠĠĠ Ġ} Ċ }