[squeak-dev] Sake/Packages

Keith Hodges keith_hodges at yahoo.co.uk
Wed Apr 9 20:35:46 UTC 2008


Dear Stephen,

thanks for your feedback and ideas.

Stephen Pair wrote:
> On Wed, Apr 9, 2008 at 1:50 AM, Keith Hodges <keith_hodges at yahoo.co.uk 
> <mailto:keith_hodges at yahoo.co.uk>> wrote:
>
>     Dear All,
>
>     For those not familiar with the idea, Sake is an attempt to
>     provide similar functionality to Make and Rake, only using
>     Smalltalk as the DSL. I hope that Sake is simple and sufficiently
>     useful for all Squeak forks make use of it.
>
>
> At work, we built something very similar to this...what you call a 
> SakeTask is similar to what we call a target.  We define them a bit 
> differently however and our targets produce one or more files in the 
> file system. 
Sake does differ from Make and Rake in that it is not primarily designed 
to work with Files... for example...

Class ensure: #Object hasSubclass: #MyClass.

Is a SakeTask which defines a non-file based target, and will create the 
subclass if it does not already exist. The api for this kind of task 
still up for debate, perhaps it would read better as a method on 
SakeTask, or a class called ClassTask. (opinions?)

You can then define a task depending upon the target like so:

myTask

    ^ SakeTask new: [ :task |
            task dependsOn: { Class ensure: #Object hasSubclass: 
#MyClass. }.
       
            task if: [ true ]. "basic isDone functionality"

            task action: [
             .....
            ]
    ]
> A target is defined by writing a method with a special pragma (this is 
> VisualWorks).  The pragma typically specifies prerequisite targets 
> (names of methods that return a filename) as well as its product 
> (usually just one method that specifies the name of some file produced).
My plan is for the package Rio, to be the basis of File based 
targets...  I have yet to work out the details, but the objective would 
be to achieve the same kind of functionality as Rake does with its 
specialised Directory classes.
>  The body of the method then does the work of producing the target 
> (producing a tarball is a typical example).  A slight variation on a 
> target is one that transforms an image...you provide the name of a 
> starting image and it launches that image, shuffles the code in the
Transforming image files, i.e building image files is also on the list, 
and was part of Sake's ruby based predecessor. To be known as "Bob", 
(the builder).
> method over to it, runs that code, then snapshots the image as the 
> filename specified as the product of the target.  The build system 
> just checks to see whether a target's product exists on disk to 
> determine whether that target has already been produced or not.  The 
> classes and methods defining targets and the code implementing the 
> build system are all versioned along with our product's code so that 
> everything is highly reproducible.  Only a small bit of bootstrapping 
> logic lives outside.  On launching a build, we gather all the methods 
> implementing these pragmas, create instances of a target class, and 
> construct a dependency graph and begin building the requested targets. 
>  This system has served us well for several years now
Excellent to hear that this kind of thing is really useful.
> I think a target/task boils do to the following operations: 
> prerequisites (identifiers of prerequisite tasks), product (some kind 
> of identifier) do, isDone, and undo (though we do not have that in our 
> system). 
The #unload functionality is implemented in Packages, rather than being 
an inherent feature of Sake. unload simply swaps the undoAction for the 
doAction block before running the task, so Sake is none the wiser.
> Does SakeTask have any means of testing isDone?
A task will not run, if it has already run in the invocation. When a 
task is run, its priorTasks are run first. Then a task consults its 
ifBlock (default being true) before actually doing the task.

hmm, perhaps I might enable multiple actions to give case-statement like 
behaviour...

task if: [ this ] do: [ that ].
task if: [ theOther ] do: [ somethingElse ].
 
Subclasses of SakeTask, i.e. SakeFileTask are able to consult the 
priorTasks' results in order to determine whether of not the task isNeeded.

for example SakeFileTask includes the following test...

isNeeded: runPriorTasks
    ....
    (runPriorTasks noneSatisfy: [ :each | each isNewerThan: self 
timeStamp ]) ifTrue: [ ^ false ].
    ....
> Also, is it generalized to the degree that do and undo actions could 
> perform pretty much any action (i.e. actions in the file system) and 
> not be tied to a concept of code packages?
the undo concept is currently only part of the Packages system, since 
the undo-dependancies rely upon knowing the full history of which 
packages were loaded afterwards.
> In any case, this looks promising.
>
> - Stephen
thanks for your detailed reply

Keith




More information about the Squeak-dev mailing list