Creating a Pharo application for MacOS

Packaging your code as an application is an important point. It is the last step that makes a difference between a bunch of packages and a complete application. 

Thanks to the beautiful work in the PharoApplicationGenerator package, developed by Pablo Tesone, it is now possible to quickly generate an application and an .dmg installer, specifying your Metacello baseline, so you can have an executable for your application.

Now you can use a one-line command to build an installer for your own Pharo macOS application.

If you just want the sample command, this is it:

wget -O- get.pharo.org/64/130+vm | bash; ./pharo Pharo.image metacello install github://hernanmd/the-note-taker/src BaselineOfTheNoteTaker --groups=Release; ./pharo Pharo.image eval "NTCommandLineHandler generateApplication"; chmod 755 build/build.sh; cd build; ./build.sh; open NoteTaker.app

Let’s dive into each step of this one-liner. We will create an installer for a sample application for the Note Taker project:

Downloading Pharo

wget -O- get.pharo.org/64/130+vm | bash

This part downloads Pharo 13.0 (64-bit) and its Virtual Machine (VM). The output is piped directly to bash for execution.

Installing the Project

./pharo Pharo.image metacello install github://hernanmd/the-note-taker/src BaselineOfTheNoteTaker --groups=Release

We’re using Metacello (Pharo’s package manager) to install “The Note Taker” project from its GitHub repository, specifically the Release group. The Release group should include a package that will be only loaded for the executable generation process and includes an NTCommandLineHandler class used to generate a build shell script.

Generating the Application

./pharo Pharo.image eval "NTCommandLineHandler generateApplication"

This step invokes a custom command line handler to generate the application. It’s worth noting that NTCommandLineHandler is a subclass of CommandLineHandler, and CommandLineHandler is already provided in vanilla Pharo images. You should implement a very simple generateApplication class method in your own “NTCommandLineHandler“. Check an example implementation for macOS in the project’s GitHub repository. (https://github.com/hernanmd/the-note-taker/blob/master/src/TheNoteTaker-Release/NTCommandLineHandler.class.st)

Here is the gist of the command line handler

NTCommandLineHandler class >> generateApplication 

  (self environment at: #AppGeneratorOSXGenerator) new
    properties: { 
    #AppName -> 'NoteTaker' .
    #InfoString -> 'A note taking application written in Pharo' .
    #BundleIdentifier -> 'org.pharo.notetaker' .
    #ShortVersion -> '1.0.0' .
    #DisplayName -> 'Note Taker' .
    #CommandLineHandler -> 'noteTaker' .
    #CompanyName -> 'INRIA' .
      #VMType -> 'Spur' } asDictionary;
    outputDirectory: FileLocator workingDirectory / 'build';
    generate.

NTCommandLineHandler >> activate

   AppGeneratorSupport errorHandler: AppGeneratorSDLMessageErrorHandler new.
   OSWindowDriver current startUp: true.

   OSPlatform current isMacOSX
    ifTrue: [ | main |
        main := CocoaMenu new.
        main    title: 'MainMenu'; "Only informative"
            addSubmenu: 'Application' with: [ :m |
                m
                    addItemWithTitle: 'Quit'
                    action: [ Smalltalk snapshot: false andQuit: true ]
                    shortcut: 'q';

                    addItemWithTitle: 'Restart'
                    action: [ NTSpApplication new start ]
                    shortcut: 's' ];
            addSubmenu: 'Help' with: [ :m |
                m
                    addItemWithTitle: 'Show Help'
                    action: [ self inform: 'Help' ]
                    shortcut: '' ].
        main setAsMainMenu.
        NTSpApplication new startFullScreen ]
    ifFalse: [ self inform: 'Not OSX' ].

Preparing the Build Script

chmod 755 build/build.sh

This command makes the build script executable.

Building the Application

cd build; ./build.sh

We change to the build directory and execute the build script. It’s important to note that the build.sh script requires the create-dmg package, which you can install via Homebrew (brew install create-dmg). This dependency is crucial for creating the macOS disk image (DMG) file.

Opening the Application

open NoteTaker.app

Finally, we will open the newly created NoteTaker application.

Conclusion

This command line showcases the power and flexibility of Pharo’s development ecosystem. It demonstrates how we can automate the entire process from downloading Pharo to building and launching a desktop application, all in one command. In future posts, we will explore how to expand this process for GNU/Linux and Windows systems.