[prev] [up] [next]

Deploying an Application

Contents

Introduction

This document gives you some information and examples on how to build a stand-alone application for deployment.

Project Definition

A project is now described by a project-definition, which is implemented as a class with protocol to return the specification. We use a class instead of xml-files or other objects, in order to make it easy to compile, deliver and maintain project definitions much like any other compilable item in the stx environment. Especially, to be able to use the browser, cvs and the stc-compiler to embed these definitions into a compilation unit (such as a dll or an exe).

Project definitions can be created manually (by entering a corresponding class definition and accepting), via the browser's "New-project" menu function, or programmatically.

The ProjectDescription class, which is the superclass of all those specifications, knows how to generate the files which are required to build the target. Such files include makefiles, resource-specifications etc.

Library Definitions

A library definition specifies a dll-target (or .so-file, in the unix world). This consists of a number of classes, optional extension-methods for other classes, preRequisite libraries and optionally load/and unload actions.

Application Definitions

Much like a library, an application definition also may include classes and extensions, but also includes product information (vendor, release, copyrights), resource information (icons and documentation files), specifications for startup (startup class and selector) and finally, specifications to generate self-installable packages for delivery (NullSoft installer files).

A Sample GUI Application

Lets start with a very simple application: a simple GUI application, which shows "hello world" in its window.
The code presented below looks a bit more complicated as required: although this example could have been programmed easier using a Label-widget, we use a private GUI widget component. This was done in order to show how additional components (View-classes) can be added to an application.

First, we create (and debug) the application within the Smalltalk/X IDE:

Defining the Sample GUI Application

The initial applications code is generated automatically via the browser's "New"-"Application" menu function:


which eventually (after a few accept actions) gives us a skeletton application.
We remove all but the "openAboutThisApplication" method from the instance protocol, and also remove most of the menu items (using the Menu-Editor, by double-clicking on the menuSpec method in the class protocol) to make the menu look like:



Using the UIPainter (double-click on the windowSpec-method in the class protocol), add a Nonscrollable-Arbitrary component to the UI, by dragging it from the gallery:

into the canvas, and change its view-class to HelloWorldView (which we will define in just a minute):

The HelloWorldView is defined as simple subclass of View:
View subclass:#DemoView
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	category:'demos-StandAlone'
and has a single redraw method on the instance side:
redraw
    |x y msg|

    msg := 'Hello World'.
    x := (self width - (font widthOf:msg)) // 2.
    y := (self height - (font heightOf:msg)) // 2.
    self displayString:msg at:(x @ y)
now, by double-clicking on the application (or the launch-icon in the UI-Painter), the following application window should appear:


Setting up the Source Code Repository

Currently, the build and deployment process depends on a CVS repository to be available for checkin of smalltalk code. If not already done, you should now create a CVS-repository and configure Smalltalk/X to use it (at least for classes in the "demo"-module).
Here, the following setup was used:

The build procedure as shown below depends on a cvs-repository to be present. Future releases of Smalltalk/X will allow for a deployment-build without a cvs repository, and also to allow for other repository types (i.e. non-CVS) to be used (especially, SubVersion and relational-DB-based storage will be supported).
Once this is implemented, the build process will look similar to the one described below.

Defining the demo-Project

Next, we have to define the package where our classes are to be stored. Packages are organized in a hierarchical fashion. For traditional reasons (and due to the cvs-history), the top hierarchy level is called the "module", and the remaining levels are called the "package-directory".
Module and directory are also visible in a package-identifier, which MUST be of the form module:directory, where module is a single word, and directory has the form of a unix path (i.e. components separated by slashes).

We recommend using different modules for the different applications - here, we use "demo" as module and "demoApp1" as directory.
In the browser, move the classes to the "demo:demoApp1" project, and then switch the browser's display-mode to "project":

and, using the projectViews "New..." menu, create a project-definition there:


(don't forget to check for the type to be "GUI-Application" and the projects name to be "demo:demoApp1" before pressing "OK". Although the browser tries hard to "do-what-you-mean", but sometimes its initial values are stupid...)

After that, you should see the new-generated project definition named "demo_demoApp1" (i.e. thats a class with the name of the package, with colons and slashes replaced by underlines in the name).
This project definition class can be handled like any other class; especially, it can be checked-in and out of the repository and it can be compiled to a binary object using the "stc" compiler.

Some more Project-Definitions

Before we are able to generate the helper files required for dll- and exe-compilation, we need to have a more detailed look at the project definition. Especially, we have to tell it, which other packages (classLibraries) are to be packaged with the app, and also check for the correct definition of the start-up code.
First change the two methods which specify the startup:
startupClassName
    ^ 'DemoApplication'
and:
startupSelector
    ^ #'open'

Second, some definitions which will identify the generated binary files (especially, under windows, this information is displayed in the windows-explorer, when you click one of the dll or exe files):
companyName
    ^ 'the wonder Company'

Finally, check the definition of the other required packages; the automatically generated code is almost always wrong.
Edit the preRequisites method as appropriate:
preRequisites
    ^ #(
	'stx:libview'
	'stx:libwidg'
	'stx:libview2'
	'stx:libui'
	'stx:libwidg2'
	'stx:libcomp'
	'stx:libbasic'
    )

Saving the Project in the Repository

Now, we are ready to check the classes and generated build support files into the repository. In the browser's project view, select the "Repository"-"Check In" menu function. This will save all of the project classes and also generate build support files, which are also checked into the repository.

The support files are:
File Description Architecture
Make.spec List of (class-)object files which are compiled Shared among all architectures
Make.proto Makefile template; included by unix-Makefile
uses Make.spec
unix
nt.mak win32 makefile
uses Make.spec
win32
bc.def win32 dll-export definitions win32
<lib>.rc win32 resource definitions
Contains vendor, version and copyright information
win32
libInit.cc initialization vector for lib
One entry per class in the dll
Shared among all architectures
modules.c initialization vector for exe
One entry per class in the exe
Shared among all architectures
modules.stx required dll definition
One entry per preRequisite classLib in the exe
Shared among all architectures
<app>.nsi NullSoft installer definitions
used to generate self-install executable
win32
To see the generated file(s) without actually checking them into the repository, select the browser's "Build" - "Show Generated" - "<file>" item from the project list menu.

Checking out and building from the Repository

Building under Windows

For now, the build must be done in a directory which is beside the installed stx directory. Therefore, we open a command window, and execute the following commands there (user input in bold):
C:\...\work\stx>cd ..
C:\...\work>dir
17.08.2006  16:50    <DIR>          .
17.08.2006  16:50    <DIR>          ..
...
17.08.2006  16:51    <DIR>          cg
17.08.2006  16:52    <DIR>          exept
13.09.2006  16:28    <DIR>          stx
...
C:\...\work>cvs -d :pserver:cg@exept.exept.de:/cvs/stx co demo
cvs checkout: Updating demo
cvs checkout: Updating demo/demoApp1
U demo/demoApp1/.cvsignore
U demo/demoApp1/DemoApplication.st
U demo/demoApp1/HelloWorldView.st
U demo/demoApp1/Make.spec
U demo/demoApp1/abbrev.stc
U demo/demoApp1/bc.def
U demo/demoApp1/bmake.bat
U demo/demoApp1/demoApp1.nsi
U demo/demoApp1/demoApp1WinRC.rc
U demo/demoApp1/demo_demoApp1.st
U demo/demoApp1/modules.c
U demo/demoApp1/modules.stx
U demo/demoApp1/nt.mak
C:\...\work>cd demo\demoApp1
C:\...\work\demo\demoApp1>bmake
...

"bmake" is a batch command to invoke make under the windows system.
For unix, use "make" instead, as in:
.../work/demo/demoApp1> make

Notice, that the above make commands generate a self-installing executable (under windows) or a zip-file (under unix) for deployment.
If you only want to compile the application without generating a deployable, make the "exe" target. (i.e. type "make exe" or "bmake exe").

You can also start a build from the browser, via the select the browser's "Build"-"Binaries" item from the project list menu.

Rebuilding after a change

If you keep the build directory around (i.e. you do not remove it after the build), a rebuild after a change is simply done by checking in the application in the browser, and re-checking out (in the command window) afterwards:
C:\...\work\demo\demoApp1>cvs upd
cvs update: Updating .
P Make.spec
U abbrev.stc
P demoApp1.nsi
P demoApp1WinRC.rc
P demo_demoApp1.st
P modules.c
P modules.stx
P nt.mak
P DemoApplication.st
C:\...\work\demo\demoApp1>bmake
...

A Sample NON-GUI Application

Most of the above is the same when building a non-GUI application (i.e. a server or other application which does not open a window).
As above, first create a "demo:demoApp2" project in the browser's project-list menu. Make sure, to choose "NonGUI-Application" from the combo list:


and create a simple HelloWorld class, with a single #start method:
Object subclass:#HelloWorld
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	category:'Demos'
the start-method must be in the class protocol (NOT on the instance side):
start
    Stdout nextPutAll: 'Hello World'
in the project definition class "demo:demoApp2", change startupClassName and startUpSelector as:
startupClassName
    ^ #'HelloWorld'
and
startupSelector
    ^ #'start'
and check the project into then repository.

Going back to the command window, check the new project out of the repository:
C:\Dokumente und Einstellungen\cg\work\demo\demoApp1>cd ..
C:\Dokumente und Einstellungen\cg\work\demo>dir
...
20.09.2006  18:18    <DIR>          demoApp1
...
C:\Dokumente und Einstellungen\cg\work\demo>cvs upd -d demoApp2
cvs update: Updating demoApp2
U demoApp2/.cvsignore
U demoApp2/HelloWorld.st
U demoApp2/Make.spec
U demoApp2/abbrev.stc
U demoApp2/bc.def
U demoApp2/bmake.bat
U demoApp2/demoApp2.nsi
U demoApp2/demoApp2WinRC.rc
U demoApp2/demo_demoApp2.st
U demoApp2/modules.c
U demoApp2/modules.stx
U demoApp2/nt.mak
C:\Dokumente und Einstellungen\cg\work\demo>dir
...
20.09.2006  18:18    <DIR>          demoApp1
20.09.2006  18:34    <DIR>          demoApp2
...
C:\...\work\demo>cd demoApp2
C:\...\work\demo\demoApp2>bmake
...
Finally, execute the program with:
C:\Dokumente und Einstellungen\cg\work\demo\demoApp2>demoApp2
Hello World
C:\Dokumente und Einstellungen\cg\work\demo\demoApp2>
Notice, that non-GUI applications are always console applications; they can read their standard-input and write to the standard-output and -error.
In case of an error, a MiniDebugger is entered, which allows for some limited command-oriented debugging.

For GUI applications, we do NOT recommend deployment without the tool classes. Having a debugger around - even in a deployed end-user application - is of so much value, that you don't want to miss it, once you and your customers got used to simply pressing "Abort" in case of an error, instead of having to restart the application from the beginning !


Copyright © 2006 eXept Software AG


Doc $Revision: 1.8 $ $Date: 2016/07/11 09:24:05 $