1 ! Copyright (C) 2007, 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays alien.libraries accessors io.backend
4 io.encodings.utf8 io.files io.streams.c init fry namespaces math
5 make assocs kernel parser parser.notes lexer strings.parser
6 vocabs sequences sequences.deep sequences.private words memory
7 kernel.private continuations io vocabs.loader system strings
8 sets vectors quotations byte-arrays sorting compiler.units
9 definitions generic generic.standard generic.single
10 tools.deploy.config combinators combinators.private classes
11 vocabs.loader.private classes.builtin slots.private grouping
12 command-line io.pathnames memoize namespaces.private
14 QUALIFIED: bootstrap.stage2
15 QUALIFIED: classes.private
16 QUALIFIED: compiler.crossref
17 QUALIFIED: compiler.errors
18 QUALIFIED: continuations
19 QUALIFIED: definitions
22 QUALIFIED: source-files
23 QUALIFIED: source-files.errors
25 QUALIFIED: vocabs.loader
26 FROM: assocs => change-at ;
27 FROM: namespaces => set ;
28 FROM: sequences => change-nth ;
29 FROM: sets => members ;
30 IN: tools.deploy.shaker
32 ! This file is some hairy shit.
34 : add-command-line-hook ( -- )
35 [ (command-line) command-line set-global ] "command-line"
36 startup-hooks get set-at ;
38 : strip-startup-hooks ( -- )
39 "Stripping startup hooks" show
46 [ startup-hooks get delete-at ] each
48 "threads" startup-hooks get delete-at
51 "io.backend" startup-hooks get delete-at
58 } [ startup-hooks get delete-at ] each
61 : strip-debugger ( -- )
62 strip-debugger? "debugger" lookup-vocab and [
63 "Stripping debugger" show
64 "vocab:tools/deploy/shaker/strip-debugger.factor"
68 : strip-ui-error-hook ( -- )
69 strip-debugger? deploy-ui? get and "ui" lookup-vocab and [
70 "Installing generic UI error hook" show
71 "vocab:tools/deploy/shaker/strip-ui-error-hook.factor"
77 "Stripping manual memory management debug code" show
78 "vocab:tools/deploy/shaker/strip-libc.factor"
82 : strip-destructors ( -- )
83 "Stripping destructor debug code" show
84 "vocab:tools/deploy/shaker/strip-destructors.factor"
88 "Stripping stack effect checking from call( and execute(" show
89 "vocab:tools/deploy/shaker/strip-call.factor" run-file ;
92 "cocoa" lookup-vocab [
93 "Stripping unused Cocoa methods" show
94 "vocab:tools/deploy/shaker/strip-cocoa.factor"
98 : strip-gobject ( -- )
99 "gobject-introspection.types" lookup-vocab [
100 "Stripping GObject type info" show
101 "vocab:tools/deploy/shaker/strip-gobject.factor"
105 : strip-gtk-icon ( -- )
106 "ui.backend.gtk" lookup-vocab [
107 "Stripping GTK icon loading code" show
108 "vocab:tools/deploy/shaker/strip-gtk-icon.factor"
112 : strip-specialized-arrays ( -- )
113 strip-dictionary? "specialized-arrays" lookup-vocab and [
114 "Stripping specialized arrays" show
115 "vocab:tools/deploy/shaker/strip-specialized-arrays.factor"
119 : strip-word-names ( words -- )
120 "Stripping word names" show
121 [ f >>name f >>vocabulary drop ] each ;
123 : strip-word-defs ( words -- )
124 "Stripping symbolic word definitions" show
125 [ "no-def-strip" word-prop not ] filter
126 [ [ ] >>def drop ] each ;
128 : strip-word-props ( stripped-props words -- )
129 "Stripping word properties" show
132 [ drop _ member? not ] assoc-filter sift-values
137 : stripped-word-props ( -- seq )
146 "effect-dependencies"
147 "definition-dependencies"
148 "conditional-dependencies"
157 "default-output-classes"
189 "predicate-definition"
227 deploy-c-types? get [
228 { "c-type" "struct-slots" "struct-align" } %
232 : strip-words ( props -- )
234 deploy-word-props? get [ 2dup strip-word-props ] unless
235 deploy-word-defs? get [ dup strip-word-defs ] unless
236 strip-word-names? [ dup strip-word-names strip-stack-traces ] when
239 : strip-memoized ( -- )
240 "Clearing memoized word caches" show
241 [ memoized? ] instances [ reset-memoized ] each ;
243 : compiler-classes ( -- seq )
244 { "compiler" "stack-checker" }
245 [ child-vocabs [ words ] map concat [ class? ] filter ]
248 : prune-decision-tree ( tree classes -- )
249 [ tuple class>type ] 2dip '[
255 [ drop _ key? not ] assoc-filter
263 : strip-compiler-classes ( -- )
265 "Stripping compiler classes" show
266 [ single-generic? ] instances
267 compiler-classes '[ "decision-tree" word-prop _ prune-decision-tree ] each
270 : recursive-subst ( seq old new -- )
275 { [ 3dup drop eq? ] [ 2nip ] }
276 ! recurse into arrays
277 { [ pick array? ] [ [ dup ] 2dip recursive-subst ] }
278 ! otherwise do nothing
283 : strip-default-method ( generic new-default -- )
285 [ "decision-tree" word-prop ]
286 [ "default-method" word-prop ] bi
290 : new-default-method ( -- gensym )
291 [ [ "No method" throw ] ( -- * ) define-temp ] with-compilation-unit ;
293 : strip-default-methods ( -- )
294 ! In a development image, each generic has its own default method.
295 ! This gives better error messages for runtime type errors, but
296 ! takes up space. For deployment we merge them all together.
298 "Stripping default methods" show
299 [ single-generic? ] instances
300 new-default-method '[ _ strip-default-method ] each
303 : vocab-tree-globals ( except names -- words )
304 [ child-vocabs [ words ] map concat ] map concat
305 swap [ first2 lookup-word ] map sift diff ;
307 : stripped-globals ( -- seq )
309 "inspector-hook" "inspector" lookup-word ,
311 source-files:source-files
313 continuations:error-continuation
314 continuations:error-thread
315 continuations:restarts
318 "disposables" "destructors" lookup-word ,
320 "functor-words" "functors.backend" lookup-word ,
326 } vocab-tree-globals %
328 ! Don't want to strip globals from test programs
329 { } { "tools" } vocab-tree-globals
330 { } { "tools.deploy.test" } vocab-tree-globals diff %
332 deploy-unicode? get [
333 { } { "unicode" } vocab-tree-globals %
337 "libraries" "alien" lookup-word ,
339 { { "yield-hook" "compiler.utilities" } }
340 { "cpu" "compiler" } vocab-tree-globals %
345 classes.private:next-method-quot-cache
346 classes.private:class-and-cache
347 classes.private:class-not-cache
348 classes.private:class-or-cache
349 classes.private:class<=-cache
350 classes.private:classes-intersect-cache
351 classes.private:implementors-map
352 classes.private:update-map
354 compiler.crossref:compiled-crossref
355 compiler.crossref:generic-call-site-crossref
357 compiler.errors:compiler-errors
362 source-files.errors:error-types
363 source-files.errors:error-observers
366 vocabs:vocab-observers
367 vocabs.loader:add-vocab-root-hook
372 { } { "layouts" } vocab-tree-globals %
374 { } { "math.partial-dispatch" } vocab-tree-globals %
376 { } { "math.vectors.simd" } vocab-tree-globals %
378 { } { "peg" } vocab-tree-globals %
382 { } { "prettyprint.config" } vocab-tree-globals %
386 \ compiler.errors:compiler-errors ,
390 : cleared-globals ( -- seq )
403 "io-thread" "io.thread" lookup-word ,
406 "initial-thread" "threads" lookup-word ,
409 strip-io? [ io-backend , ] when
415 } vocab-tree-globals %
417 "windows-messages" "windows.messages" lookup-word [ , ] when*
420 : strip-global? ( name stripped-globals -- ? )
421 '[ _ member? ] [ tuple? ] bi or ;
423 : clear-global? ( name cleared-globals -- ? )
424 '[ _ member? ] [ string? ] bi or ;
426 : strip-globals ( -- )
428 "Stripping globals" show
429 stripped-globals :> to-strip
430 cleared-globals :> to-clear
432 [ drop to-strip strip-global? not ] assoc-filter!
435 swap to-clear clear-global?
436 [ f swap value<< ] [ drop ] if
442 ! On all platforms, if deploy-io is 1, we strip out C streams.
443 ! On Unix, if deploy-io is 3, we strip out C streams as well.
444 ! On Windows, even if deploy-io is 3, C streams are still used
445 ! for the console, so don't strip it there.
447 native-io? os windows? not and
449 "Stripping C I/O" show
450 "vocab:tools/deploy/shaker/strip-c-io.factor" run-file
453 : compress ( pred post-process string -- )
454 "Compressing " prepend show
455 [ instances dup H{ } clone [ [ ] cache ] curry map ] dip call
458 : compress-object? ( obj -- ? )
460 { [ dup array? ] [ empty? ] }
461 { [ dup byte-array? ] [ drop t ] }
462 { [ dup string? ] [ drop t ] }
463 { [ dup wrapper? ] [ drop t ] }
467 : compress-objects ( -- )
468 [ compress-object? ] [ ] "objects" compress ;
470 : remain-compiled ( old new -- old new )
471 ! Quotations which were formerly compiled must remain
474 2dup [ quot-compiled? ] [ quot-compiled? not ] bi* and
475 [ nip jit-compile ] [ 2drop ] if
478 : compress-quotations ( -- )
479 [ quotation? ] [ remain-compiled ] "quotations" compress
480 [ quotation? ] instances [ f >>cached-effect f >>cache-counter drop ] each ;
484 : [:c] ( -- word ) ":c" "debugger" lookup-word ;
486 : [print-error] ( -- word ) "print-error" "debugger" lookup-word ;
488 : deploy-startup-quot ( word -- )
491 startup-hooks get values concat %
492 strip-debugger? [ , ] [
493 ! Don't reference 'try' directly since we don't want
494 ! to pull in the debugger and prettyprinter into every
499 [ _ execute( obj -- ) ] [
500 _ execute( obj -- ) nl
505 strip-io? [ [ flush ] % ] unless
510 : startup-stripper ( -- )
511 t parser-quiet? set-global
512 f output-stream set-global
513 [ V{ "resource:" } clone vocab-roots set-global ]
514 "vocabs.loader" startup-hooks get-global set-at ;
516 : next-method* ( method -- quot )
517 [ "method-class" word-prop ]
518 [ "method-generic" word-prop ] bi
521 : calls-next-method? ( method -- ? )
522 def>> flatten \ (call-next-method) swap member-eq? ;
524 : compute-next-methods ( -- )
525 [ standard-generic? ] instances [
526 "methods" word-prop values [ calls-next-method? ] filter
527 [ dup next-method* "next-method" set-word-prop ] each
529 "vocab:tools/deploy/shaker/next-methods.factor" run-file ;
531 : (clear-megamorphic-cache) ( i array -- )
532 ! Can't do any dispatch while clearing caches since that
533 ! might leave them in an inconsistent state.
535 2dup [ f ] 2dip set-array-nth
536 [ 1 + ] dip (clear-megamorphic-cache)
539 : clear-megamorphic-cache ( array -- )
540 [ 0 ] dip (clear-megamorphic-cache) ;
542 : find-megamorphic-caches ( -- seq )
543 "Finding megamorphic caches" show
544 [ standard-generic? ] instances [ def>> third ] map ;
546 : clear-megamorphic-caches ( cache -- )
547 "Clearing megamorphic caches" show
548 [ clear-megamorphic-cache ] each ;
550 : write-vocab-manifest ( vocab-manifest-out -- )
551 "Writing vocabulary manifest to " write dup print flush
552 vocabs "VOCABS:" prefix
553 deploy-libraries get [ library path>> ] map members "LIBRARIES:" prefix append
554 swap utf8 set-file-lines ;
556 : prepare-deploy-libraries ( -- )
557 "Preparing deployed libraries" show
558 deploy-libraries get [
560 [ path>> >deployed-library-path ] [ abi>> ] bi <library>
565 "deploy-libraries" "alien.libraries" lookup-word forget
566 "deploy-library" "alien.libraries" lookup-word forget
567 ">deployed-library-path" "alien.libraries.private" lookup-word forget
568 ] with-compilation-unit ;
570 : strip ( vocab-manifest-out -- )
571 [ write-vocab-manifest ] when*
573 prepare-deploy-libraries
582 strip-specialized-arrays
585 add-command-line-hook
587 strip-default-methods
588 strip-compiler-classes
589 ! we can't use the Factor debugger or Factor I/O anymore
590 f ERROR-HANDLER-QUOT set-special-object
591 deploy-vocab get vocab-main deploy-startup-quot
592 find-megamorphic-caches
599 clear-megamorphic-caches ;
601 : die-with ( error original-error -- * )
602 #! We don't want DCE to drop the error before the die call!
603 [ die 1 exit ] ( a -- * ) call-effect-unsafe ;
605 : die-with2 ( error original-error -- * )
606 #! We don't want DCE to drop the error before the die call!
607 [ die 1 exit ] ( a b -- * ) call-effect-unsafe ;
609 : deploy-error-handler ( quot -- )
612 [ original-error get die-with2 ]
613 ! Don't reference these words literally, if we're stripping the
614 ! debugger out we don't want to load the prettyprinter at all
615 [ [:c] execute( -- ) nl [print-error] execute( error -- ) flush ] if
619 : (deploy) ( final-image vocab-manifest-out vocab config -- )
620 #! Does the actual work of a deployment in the slave
626 "tools.errors" require
629 "ui.debugger" require
632 [ deploy-vocab set ] [ require ] [
634 "Vocabulary has no MAIN: word." print flush 1 exit
638 "Saving final image" show
640 ] deploy-error-handler
645 "vocab-manifest-out" get
647 "Deploying " write dup write "..." print
648 "deploy-config" get parse-file first