Creating a Simple Runtime
I received a question about creating a runtime image via my chatback widget this morning - I've done screencasts on that, but those use BottomFeeder as an example. While that's a real example, it's also fairly large, and somewhat complex. So - I thought a very simple example might be useful.
First, I created a new package, and then a new class (subclassed from Object) with no instance variables.
Smalltalk defineClass: #Sample
superclass: #{Core.Object}
indexedType: #none
private: false
instanceVariableNames: ''
classInstanceVariableNames: ''
imports: ''
category: ''
I gave this class one method:
doMyThing Transcript show: 'This is from the Sample App'; cr. ObjectMemory quit.
So that the results are clear, I ran the application in headless mode - the Transcript write drops to a file called 'headless-transcript.log' (that's configurable, but never mind). Next, I need a way to have this application startup. I created a new class:
Smalltalk defineClass: #SampleUserApp
superclass: #{Core.UserApplication}
indexedType: #none
private: false
instanceVariableNames: ''
classInstanceVariableNames: ''
imports: ''
category: ''
That's a class that exists to define a startup procedure. You create a new method called #main, and put your startup code there:
main Sample new doMyThing.
Next, I need a script that creates a new image, and puts it into "runtime" mode - the #main method will not fire unless the image is in that state. Here's the script:
"build a simple app"
"load all my needed parcels (Non-Windows)"
[#('SampleApp.pcl') do: [:each |
Parcel loadParcelFrom: each]]
on: MissingParcelSource
do: [:ex | ex resume: true].
"turn change log off, so that we can ship patches reasonably"
'ChangeSet.BroadcastChanges' asQualifiedReference
ifDefinedDo: [:flag | 'ChangeSet.BroadcastChanges' asQualifiedReference value: false].
"Set herald string"
ObjectMemory setHeraldString: 'This is an Example Application in VisualWorks'.
"reset parcel path"
Parcel searchPathModel value removeAll.
"set up runtime state"
DeploymentOptionsSystem current startInRuntime: true.
"set up runtime state"
UI.WindowManager noWindowBlock: [:windowManager | ].
stream := WriteStream on: String new.
stream nextPutAll: 'changeRequest'; cr; cr; tab.
stream nextPutAll: '^true'.
VisualLauncher compile: stream contents.
VisualLauncher allInstances do: [:each | each closeAndUnschedule. each release].
ObjectMemory garbageCollect.
Workbook allInstances do: [:each | each closeRequest].
(Delay forSeconds: 20) wait.
Parcel searchPathModel value: (List with: (PortableFilename named: '.')).
SourceFileManager default discardSources.
"Now save the image such that this file does not get looked for at startup"
[ObjectMemory permSaveAs: 'sample' thenQuit: false] fork.
[(Delay forSeconds: 45) wait.
RuntimeSystem isRuntime ifFalse: [ObjectMemory quit]] fork
I saved the code I created to a parcel, so that I could do a clean load. On my Mac, the command line looked like this (I have a symlink from visual to where the VM actually resides):
./visual visual.im -filein sampleDeploy.st
Where 'sampleDeploy.st' is the script above. Running that drops a single line to 'headless-transcript.log' and quits, just as you would expect. You can copy the script from above, and download the example parcel here.
Technorati Tags: smalltalk, deployment, build script




