@@ -13,6 +13,7 @@ import {
1313 JacsDiagnostic ,
1414 DEVS_BYTECODE_FILE ,
1515 formatDiagnostics ,
16+ LogInfo ,
1617} from "devicescript-compiler"
1718import { BINDIR , CmdOptions , debug , error , log } from "./command"
1819import { devtools } from "./devtools"
@@ -78,15 +79,15 @@ async function compileBuf(buf: Buffer, options: BuildOptions) {
7879 host,
7980 isLibrary : options . library ,
8081 } )
81- if ( ! res . success ) throw new CompilationError ( "compilation failed" )
82- return res . binary
82+ return res
8383}
8484
8585export interface BuildOptions {
8686 noVerify ?: boolean
8787 library ?: boolean
8888 outDir ?: string
8989 watch ?: boolean
90+ stats ?: boolean
9091
9192 // internal option
9293 mainFileName ?: string
@@ -104,6 +105,7 @@ export async function build(file: string, options: BuildOptions & CmdOptions) {
104105 return
105106 }
106107
108+ log ( `building ${ file } ` )
107109 ensureDirSync ( options . outDir )
108110 await buildOnce ( file , options )
109111 if ( options . watch ) await buildWatch ( file , options )
@@ -128,19 +130,61 @@ async function buildWatch(file: string, options: BuildOptions) {
128130 await devtools ( { ...options , bytecodeFile } )
129131}
130132
133+ function roundWithPrecision (
134+ x : number ,
135+ digits : number ,
136+ round = Math . round
137+ ) : number {
138+ digits = digits | 0
139+ // invalid digits input
140+ if ( digits <= 0 ) return round ( x )
141+ if ( x == 0 ) return 0
142+ let r = 0
143+ while ( r == 0 && digits < 21 ) {
144+ const d = Math . pow ( 10 , digits ++ )
145+ r = round ( x * d + Number . EPSILON ) / d
146+ }
147+ return r
148+ }
149+ function prettySize ( b : number ) {
150+ b = b | 0
151+ if ( b === 0 ) return "0kb"
152+ else if ( b < 100 ) return b + "b"
153+ else if ( b < 1000 ) return roundWithPrecision ( b / 1e3 , 2 ) + "kb"
154+ else if ( b < 1000000 ) return roundWithPrecision ( b / 1e3 , 1 ) + "kb"
155+ else return roundWithPrecision ( b / 1e6 , 1 ) + "mb"
156+ }
157+
131158async function buildOnce ( file : string , options : BuildOptions & CmdOptions ) {
132- const { watch } = options
133- try {
134- if ( ! pathExistsSync ( file ) )
135- throw new Error ( `source file ${ file } not found` )
136- const buf = readFileSync ( file )
137- await compileBuf ( buf , { ...options , mainFileName : file } )
138- } catch ( e ) {
139- if ( options . verbose ) {
140- debug ( e . message )
141- debug ( e . stack )
142- }
143- if ( e instanceof CompilationError && watch ) return
144- throw e
159+ const { watch, stats } = options
160+ if ( ! pathExistsSync ( file ) ) throw new Error ( `source file ${ file } not found` )
161+ const buf = readFileSync ( file )
162+ const { success, binary, dbg, clientSpecs } = await compileBuf ( buf , {
163+ ...options ,
164+ mainFileName : file ,
165+ } )
166+ if ( ! success ) {
167+ if ( watch ) return
168+ throw new CompilationError ( "compilation failed" )
169+ }
170+
171+ log ( `binary: ${ prettySize ( binary . length ) } ` )
172+ if ( stats ) {
173+ const { sizes, functions } = dbg
174+ log (
175+ " " +
176+ Object . keys ( sizes )
177+ . map ( name => `${ name } : ${ prettySize ( sizes [ name ] ) } ` )
178+ . join ( ", " )
179+ )
180+ log ( ` functions:` )
181+ functions
182+ . sort ( ( l , r ) => l . size - r . size )
183+ . forEach ( fn => {
184+ log ( ` ${ fn . name } (${ prettySize ( fn . size ) } )` )
185+ fn . users . forEach ( user =>
186+ debug ( ` <-- ${ user . file } : ${ user . line } , ${ user . col } ` )
187+ )
188+ } )
145189 }
146190}
0 commit comments