Skip to content

build_cli

Zwetan Kjukov edited this page May 15, 2016 · 5 revisions

Building CLI Programs

Command-line interface (wikipedia)

A command-line interface or command language interpreter (CLI),
also known as command-line user interface, console user interface,
and character user interface (CUI), is a means of interacting with
a computer program where the user (or client) issues commands to
the program in the form of successive lines of text (command lines).

Basically a command-line program is an executable that interpret input, do some work and sometimes provide some output.

You can have different types of input and output, and can have numerous categories of command-line programs: some interact with the user, some talk to remote client via sockets, some other only write things in log files, etc.

Our goal is to be able to build those type of programs easily and be able to distribute them on multiple platforms: Windows, Mac OS X and Linux.

Where to install CLI Programs ?

It can vary a lot depending on what the program is actually doing.

In a general manner, following the Filesystem Hierarchy Standard is our best bet.

This FHS works with Mac OS X and Linux as they follow POSIX (even if you can have some exceptions) but is kind of counter nature to Windows operating systems as they do not really follow POSIX.

Well, we will then force POSIX into Windows or at least assume that the CLI program we produce are meant to be run on Windows operating systems setup in such a way they can be compatible with POSIX.

Please follow Redtamarin Windows Environment Setup.

Yes, it is a big and hard dependency to have to just distribute and install a "little" command-line executable, but once we have things "in place" we will then be able to focus on the very peculiar case of Windows CLI programs.

So, following the Filesystem Hierarchy Standard we can have different scenarios to where a CLI executable and other files could be installed: /usr, /usr/local, /opt/local and /opt.

Special consideration for Redtamarin executable

A redtamarin executable is basically a runtime that embed either an ABC or SWF file, we call those projectors.

When those projectors are executed they autodetect the embedded file and execute it.

when you execute $ myprogram
it is the equivalent of
$ redshell myprogram.abc
or
$ redshell myprogram.swf

Now, there is a little bug in those projectors.

When you install a command-line executable in your path, for example /usr/bin, you can then call it from any path in your system with $ myprogram.

The shell will search your PATH to find "myprogram", you type "myprogram" but then /usr/bin/myprogram is called.

The bug is that the redtamarin runtimes can be confused and think the runtime itself is called and not run the program embedded inside the projector.

So, if you run $ myprogram you receive the default output of the redshell runtime.

see exe projector does not execute from $PATH (found out where the problem is but not implemented yet).

That means we need a little wrapper script to call our executables (or projectors).

For example:
/usr/bin/helloworld
will be a wrapper containing

#!/bin/sh
/usr/lib/helloworld/bin/helloworld $@
  • the full path to the real executable
  • followed by $@, the shell replace $@ with any arguments you provided

Note:
in retrospect it's good this bug happened
as it forced me to investigate packages, FHS, etc.
otherwise I could have been tempted to just install
CLI programs with "just drop'em in your $PATH"

/usr

For software managed by the system packager, and so following the standard unix deployment rules.

/usr/bin/helloworld -> /usr/lib/helloworld/bin/helloworld
/etc/helloworld/config.conf
/usr/lib/helloworld/bin/helloworld
/usr/share/doc/helloworld/license.html
/usr/share/man/man1/helloworld.1

/usr/local

For software not managed by the system packager, but still following the standard unix deployment rules.

/usr/local/bin/helloworld -> /usr/lib/helloworld/bin/helloworld
/usr/local/etc/helloworld/config.conf
/usr/local/lib/helloworld/bin/helloworld
/usr/local/share/doc/helloworld/license.html
/usr/local/share/man/man1/helloworld.1

/opt/local

Special case for Mac OS X (with macports)

/opt/local/bin/helloworld -> /usr/lib/helloworld/bin/helloworld
/opt/local/etc/helloworld/config.conf
/opt/local/lib/helloworld/bin/helloworld
/opt/local/share/doc/helloworld/license.html
/opt/local/share/man/man1/helloworld.1

/opt

For Linux software not following the standard unix deployment rules.

/opt/helloworld
/opt/helloworld/bin/helloworld
/opt/helloworld/docs/documentation.md
/opt/helloworld/config.conf

Note:
the binary need to be called with its
full path /opt/helloworld/bin/helloworld

What I would Advise

Use either /usr or /usr/local while following the FHS.

If you go with /opt is, in general, because you first developed your command-line tool for Windows while ignoring the FHS.

It is much harder to move away from /opt to follow the FHS than doing the opposite, eg. first package for Linux with the FHS in mind, then later adapt for Windows if you need to.

The Bare Minimum for a CLI Program

Technically, once this bug exe projector does not execute from $PATH is fixed in Redtamarin, you would only need to install the executable in /usr/bin/program or /usr/bin/local/program.

But wait, users using the command-line interface deserve a bit more than that

  • your command-line executable should provide a "help" flag
    $ program -h or $ program --help
  • it would be nice too to provide a "version" flag
    $ program -v or $ program --version
  • you would want to include a manual
    $ man program
  • you would also want to include other types of documentation
    like a README, a CHANGELOG, a LICENSE, etc.
  • and maybe other files

By default in the different build scripts all that will be automatically build for you.

Wether you use make-linux-deb, make-macosx-pkg, etc.
here what will happen by default

  • the file src/version.properties will be used
    to version your build, the package, the manual, etc.
  • If the manual template is not found in /man/program.1.md
    it will be automatically created for you
  • if the manual is found, it will be updated
    with the name of the program, the version, the current date, the author, etc.
  • if the CHANGELOG.md file is not found
    it will be automatically created for you
  • if the test_man file is not found
    it will be automatically created for you

As a developer building a command-line program here the things you need to edit

  • the file src/version.properties
    to inform of the semantic version of your program
    default is 1.0.0

  • the build script variables
    for example

    var NAME:String                     = "helloworld";
    var DATE:Date                       = new Date();
    var DESC:String                     = "The Hello World program.";
    var PKGID:String                    = "com.corsaair.helloworld";
    var BASEDEST:String                 = "/usr/local";
    var AUTHOR:String                   = "Zwetan Kjukov";

That's about it, the rest is about writing and testing your program.

Other files you may need to edit or create are

  • the build.as3 redbean build
  • the build-ARCH.as3 redbean build
    replace ARCH with either linux, macosx, windows, etc.
  • the README.md file
  • the LICENSE.md file
  • the CHANGELOG.md file
    or edit the one the build is creating for you
  • the /man/program.1.md file
    or edit the one the build is creating for you
  • etc.

Those files are considered "optional", if you don't want to use them then simply edit the build script (for ex: make-linux-deb) and remove or comment out the lines you don't need.

At the contrary if you need more, edit the build script to deal with more.

Other case would be the default templates, for example if you don't like or want to change the default License HTML template in build/templates/license.html.tpl, simply edit it.

The point is that this build script is a basic skeleton that does some basic things by default but it would be impossible to cover all the different needs and configurations of any possible command-line programs, so you will need to edit and even heavily edit it for your needs.

Clone this wiki locally