Distributing Ring Applications using Ring2EXE

In this chapter we will learn about distributing Ring applications.

Starting from Ring 1.6 we have a nice tool called Ring2EXE (Written in Ring itself)

Using Ring2EXE we can distribute applications quickly for Windows, Linux, macOS, WebAssembly and Mobile devices

Note

We can use the Distribute Menu in the Ring Notepad application (More Easy)

Using Ring2EXE

ring2exe filename.ring [Options]

This will set filename.ring as input to the program

The next files will be generated

filename.ringo          (The Ring Object File - by Ring Compiler)
filename.c              (The C Source code file
                         Contains the ringo file content
                         Will be generated by this program)
filename_buildvc.bat    (Will be executed to build filename.c using Visual C/C++)
filename_buildgcc.bat   (Will be executed to build filename.c using GNU C/C++)
filename_buildclang.bat (Will be executed to build filename.c using CLang C/C++)
filename.obj            (Will be generated by the Visual C/C++ compiler)
filename.exe            (Will be generated by the Visual C/C++ Linker)
filename                (Executable File - On Linux & MacOS X platforms)

How Ring2EXE works?

At first the Ring compiler will be used to generate the Ring object file (*.ringo)

If we have a C compiler (optional), This object file will be embedded inside a C source code file

Then using the C compiler and the Ring library (Contains the Ring Virtual Machine) the executable file

will be generated!

If we don’t have a C compiler, the Ring executable will be copied and renamed to your application name

And your Ring object file (*.ringo) will become ring.ringo to be executed at startup of the executable file.

So it’s better and easy to have a C compiler on your machine to be used by Ring2EXE.

Example

We have test.ring contains the next code

see "Hello, World!" + nl

To build the executable file for Windows, Linux or macOS

ring2exe test.ring

To run the program (Windows)

test

To run the program (Linux and macOS)

./test

Options

-keep            : Don't delete Temp. Files
-static          : Build Standalone Executable File
                   (Don't use ring.dll/ring.so/ring.dylib)
-gui             : Build GUI Application (Hide the Console Window)
-dist            : Prepare application for distribution
-allruntime      : Include all libraries in distribution
-mobileqt        : Prepare Qt Project to distribute Ring Application for Mobile
-webassemblyqt   : Prepare Qt Project to distribute Ring Application for the web (WebAssembly)
-noqt            : Remove RingQt from distribution
-noallegro       : Remove RingAllegro from distribution
-noopenssl       : Remove RingOpenSSL from distribution
-nolibcurl       : Remove RingLibCurl from distribution
-nomysql         : Remove RingMySQL from distribution
-noodbc          : Remove RingODBC from distribution
-nosqlite        : Remove RingSQLite from distribution
-noopengl        : Remove RingOpenGL from distribution
-nofreeglut      : Remove RingFreeGLUT from distribution
-nolibzip        : Remove RingLibZip from distribution
-noconsolecolors : Remove RingConsoleColors from distribution
-nomurmuhash     : Remove RingMurmurHash from distribution
-nocruntime      : Remove C Runtime from distribution
-qt              : Add RingQt to distribution
-allegro         : Add RingAllegro to distribution
-openssl         : Add RingOpenSSL to distribution
-libcurl         : Add RingLibCurl to distribution
-mysql           : Add RingMySQL to distribution
-odbc            : Add RingODBC to distribution
-sqlite          : Add RingSQLite to distribution
-postgresql      : Add RingPostgreSQL to distribution
-opengl          : Add RingOpenGL to distribution
-freeglut        : Add RingFreeGLUT to distribution
-libzip          : Add RingLibZip to distribution
-libuv           : Add RingLibuv to distribution
-consolecolors   : Add RingConsoleColors to distribution
-murmurhash      : Add RingMurmurHash to distribution
-cruntime        : Add C Runtime to distribution

Building standalone console application

Using the “-static” option we can build executable console application

So we don’t have to use ring.dll, ring.so or ring.dylib

This avoid only the need to Ring dynamic link library

If you are using another libraries, You will need to include it with your application.

ring2exe test.ring -static

Distributing RingAllegro Applications

We have test2.ring contains the next code

# Just a simple program to test Ring2EXE Tool!
# Using RingAllegro

load "gameengine.ring"  # Give Control to the Game Engine

func main               # Called by the Game Engine

        oGame = New Game        # Create the Game Object
        {
                title = "My First Game"
        }

To build the executable file and prepare for distributing the Game

We use “-dist” option and “-allruntime” to include all libraries

ring2exe test2.ring -dist -allruntime

After executing the previous command

On Windows we will have : target/windows folder

On Linux we will have : target/linux folder

On macOS we will have : target/macos folder

The previous command will add all of the Ring runtime libraries to our distribution

But we may need only RingAllegro, So it’s better to use the next command

ring2exe test2.ring -dist -allegro -cruntime

This will produce smaller size distribution and will avoid the runtime files that we don’t need!

Also we could use the “-gui” option to hide the console window

So it’s better to use the next command

ring2exe test2.ring -dist -gui -allegro -cruntime

Distributing RingQt Applications

We have test3.ring contains the next code

# Just a simple program to test Ring2EXE Tool!
# Using RingQt

load "guilib.ring"

new qApp {
        new qWidget() {
                setwindowtitle("Hello, World!")
                resize(400,400)
                show()
        }
        exec()
}

To build the executable file and prepare for distributing the GUI application

We use “-dist” option and “-allruntime” to include all libraries

ring2exe test3.ring -dist -allruntime

After executing the previous command

On Windows we will have : target/windows folder

On Linux we will have : target/linux folder

On macOS we will have : target/macos folder

The previous command will add all of the Ring runtime libraries to our distribution

But we may need only RingQt, So it’s better to use the next command

ring2exe test3.ring -dist -qt -cruntime

This will produce smaller size distribution and will avoid the runtime files that we don’t need!

Also we could use the “-gui” option to hide the console window

So it’s better to use the next command

ring2exe test3.ring -dist -gui -qt -cruntime

Distributing Applications for Mobile using RingQt

To prepare a Qt project for your RingQt application (test3.ring) use the “-mobileqt” option

Example :

ring2exe test3.ring -dist -mobileqt

After executing the previous command, We will have the Qt project in target/mobile/qtproject folder

The main project file will be project.pro which we can open using the Qt Creator IDE.

Also we will have the resource file : project.qrc

Another important file is our C++ main file : main.cpp

Distributing Applications for WebAssembly using RingQt

To prepare a Qt project (WebAssembly) for your RingQt application (myapp.ring) use the “-webassemblyqt” option

Example :

ring2exe myapp.ring -dist -webassemblyqt

After executing the previous command, We will have the Qt project in target/webassembly/qtproject folder

The main project file will be project.pro which we can open using the Qt Creator IDE.

Also we will have the resource file : project.qrc

Another important file is our C++ main file : main.cpp

Building the Cards Game for Mobile using RingQt

For a better example, consider building an Android package for the Cards game that comes with the

Ring language in this folder : ring/application/cards

The Cards game folder contains three files

cards.ring : The Game source code

cards.jpg : The image file used by the game

project.qrc : Resource file to be used with the Qt project

The resource file contains the next content

<RCC>
        <qresource>
                <file>cards.ringo</file>
                <file>cards.jpg</file>
        </qresource>
</RCC>

We have two files in the resource file

The first file is cards.ringo (The Ring Object File) and the second file is cards.jpg (The image file)

As a start, Ring2EXE will generate this resource file in target/mobile/qtproject/project.qrc

But this file will contains only cards.ringo (That Ring2EXE will generate by calling Ring compiler)

We need to update this resource file to add the image file : cards.jpg

After this update, we copy the resource file to the main application folder

So when we use Ring2EXE again, Our updated resource file will be used!

Now to build the cards game for Mobile

  1. Run the next command

ring2exe cards.ring -dist -mobileqt
  1. Open target/mobile/qtproject/project.pro using Qt creator

  2. Build and Run using Qt Creator

How the Cards game will find the image file ?

RingQt comes with a simple function : AppFile() that we can use to determine the files that we may

access on Desktop or Mobile platforms

The next code from cards.ring

mypic = new QPixmap(AppFile("cards.jpg"))

So all what you need is using AppFile() function around your image files!

Building the Weight History Application for Mobile using RingQt

Another example to distribute your application for Mobile Devices using Ring2EXE and Qt

consider building an Android package for the Weight History application that comes with the

Ring language in this folder : ring/application/weighthistory

The Weight History application folder contains four files

weighthistory.ring : The application source code

weighthistory.db : The SQLite database

project.qrc : The resource file for the Qt project

main.cpp : The main C++ source file for the Qt project

To build the Weight History application for Mobile

  1. Run the next command

ring2exe weighthistory.ring -dist -mobileqt
  1. Open target/mobile/qtproject/project.pro using Qt creator

  2. Build and Run using Qt Creator

The resource file (project.qrc) contains two files

<RCC>
        <qresource>
                <file>weighthistory.ringo</file>
                <file>weighthistory.db</file>
        </qresource>
</RCC>

The first file is weighthistory.ringo (Ring Object File - Generated by Ring2EXE by calling Ring compiler)

The database file : weighthistory.db

The main.cpp contains the next little update, To copy the database file from resources to a writable location

on the mobile device

QString path3 ;
path3 = path+"/weighthistory.db";
QFile::copy(":/weighthistory.db",path3);

You will need to do this with database files only!

When we use Ring2EXE, the tool will check for project.qrc and main.cpp, if they exist then your updated

files will be used in target/mobile/qtproject instead of the default version generated by Ring2EXE

So Use Ring2EXE to generate these files, Then copy them to your application folder when you update them.

Building the Form Designer for Mobile using RingQt

To build the Form Designer application (ring/tools/formdesigner) for Mobile

  1. Run the next command

ring2exe formdesigner.ring -dist -mobileqt
  1. Open target/mobile/qtproject/project.pro using Qt creator

  2. Build and Run using Qt Creator

in the folder ring/application/formdesigner You will find the resource file : project.qrc

It will be used automatically by Ring2EXE

<RCC>
        <qresource>
                <file>formdesigner.ringo</file>
                <file>image/allevents.png</file>
                <file>image/checkbox.png</file>
                <file>image/close.png</file>
                <file>image/combobox.bmp</file>
                <file>image/datepicker.bmp</file>
                <file>image/dial.png</file>
                <file>image/formdesigner.png</file>
                <file>image/frame.png</file>
                <file>image/grid.bmp</file>
                <file>image/hyperlink.png</file>
                <file>image/image.png</file>
                <file>image/label.png</file>
                <file>image/layout.png</file>
                <file>image/lcdnumber.png</file>
                <file>image/listview.png</file>
                <file>image/lock.png</file>
                <file>image/new.png</file>
                <file>image/open.png</file>
                <file>image/progressbar.png</file>
                <file>image/project.png</file>
                <file>image/pushbutton.png</file>
                <file>image/radiobutton.png</file>
                <file>image/save.png</file>
                <file>image/saveas.png</file>
                <file>image/select.png</file>
                <file>image/slider.png</file>
                <file>image/spinner.bmp</file>
                <file>image/statusbar.png</file>
                <file>image/tab.png</file>
                <file>image/textarea.png</file>
                <file>image/textfield.png</file>
                <file>image/timer.png</file>
                <file>image/toolbar.png</file>
                <file>image/tree.bmp</file>
                <file>image/videowidget.png</file>
                <file>image/webview.png</file>
        </qresource>
</RCC>

As we did in the Cards game, The Form Designer will use the AppFile() function to determine the name of the Image files.

The next code from ring/tools/formdesigner/mainwindow/formdesignerview.ring

func CreateToolBar
        aBtns = [
                        new qtoolbutton(win) {
                                setbtnimage(self,AppFile("image/new.png"))
                                setclickevent(Method(:NewAction))
                                settooltip("New File")
                        } ,
                        new qtoolbutton(win) {
                                setbtnimage(self,AppFile("image/open.png"))
                                setclickevent(Method(:OpenAction))
                                settooltip("Open File")
                        } ,
                        new qtoolbutton(win) {
                                setbtnimage(self,AppFile("image/save.png"))
                                setclickevent(Method(:SaveAction))
                                settooltip("Save")
                         } ,
                        new qtoolbutton(win) {
                                setbtnimage(self,AppFile("image/saveas.png"))
                                setclickevent(Method(:SaveAsAction))
                                settooltip("Save As")
                         } ,
                        new qtoolbutton(win) {
                                setbtnimage(self,AppFile("image/close.png"))
                                setclickevent(Method(:ExitAction))
                                settooltip("Exit")
                        }
                ]

        tool1 = win.addtoolbar("files")  {
                for x in aBtns { addwidget(x) addseparator() }
        }

From this example, We know that we can use sub folders for images.

Creating the Qt resource file using Folder2qrc

When we have large RingQt project that contains a lot of images and files, We need to add these files to the resource file ( *.qrc ) when distributing applications for Mobile devices.

Instead of adding these files one by one, Ring 1.6 comes with a simple tool that save our time, It’s called Folder2qrc.

Example:

folder2qrc formdesigner.ring

We determine the main source file while we are in the application folder, and Folder2qrc will check all of the files in the current folder and sub folders, Then add them to the resource file after the mainfile.ringo (In our example this will be formdesigner.ringo)

The output file will be : project.qrc

You can open it and remove the files that you don’t need in the resources!

Important Information about Ring2EXE

  • Using Ring2EXE to prepare distribution will delete all of the files in the old distribution

for example, if you have target/windows folder then used

ring2exe test3.ring -dist -allruntime

The files in target/windows will be deleted before adding the files again

This is important when you prepare a distribution for Mobile devices

ring2exe test3.ring -dist -mobileqt

If you modified the resource file : project.qrc or the main file : main.cpp

Don’t forget to copy them to the application folder!

So Ring2EXE can use the updated version if you tried the previous command again!

automatically to support new libraries