Friday, June 21, 2019

Linux Mint: Compile the Lua interpreter from source and build your own Debian package to install it

Objective


Compile the latest version of the Lua language interpreter from source. First build a locally installed Lua interpreter for the current user only. Finally, build a Debian package to install it and have the possibility to safely remove it when necessary.

Motivation


Recently, I thought it was a good idea to learn a new programming language that can be easily integrated and combined with C++. After a quick research I figured that Lua would be very handy for such a job. Unfortunately, my current Mint version does not quite support the latest Lua version in it's repository. Additionally, I plan to use Lua from Windows 10, too. So, I wanted to have the installation build from the same sources for both Operating Systems as well. This article describes the process to get a local portable installation of Lua on per user basis and a description on how to build a Debian installer package for Linux that can be easily uninstalled again. An upcoming article will describe how to compile your own Lua interpreter on Windows 10 using the (command line interface) CLI compiler from Microsoft e.g. Visual Studio Professional.

Prerequisites



Solution


I decided to do the whole build and temporary stuff within a "tmp" folder in my home account.
The boostrap toolchain will reside in the sub-directory "lua" within the "tmp" folder.

Get the latest source of the Lua interpreter from their homepage


Open a terminal and change the current directory to "~/tmp". Type the following commands to dowload the latest version of the source code of the Lua interpreter, in my case version 5.3.5.

$> mkdir -p ~/tmp/lua
$> cd ~/tmp/lua
$> wget https://www.lua.org/ftp/lua-5.3.5.tar.gz

you'll see some output similar to this:

--2019-06-19 21:34:32-- https://www.lua.org/ftp/lua-5.3.5.tar.gz
Resolving www.lua.org (www.lua.org)... 88.99.213.221, 2a01:4f8:10a:3edc::2
Connecting to www.lua.org (www.lua.org)|88.99.213.221|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 303543 (296K) [application/gzip]
Saving to: ‘lua-5.3.5.tar.gz’

lua-5.3.5.tar.gz 100%[===============================================================>] 296,43K --.-KB/s in 0,1s

2019-06-19 21:34:32 (2,56 MB/s) - ‘lua-5.3.5.tar.gz’ saved [303543/303543]

Now you have to unpack the downloaded package:

$> tar -xzvf lua-5.3.5.tar.gz

Everything will be unpacked into the sub-directory "lua-5.3.5"

lua-5.3.5/
lua-5.3.5/Makefile
lua-5.3.5/doc/
lua-5.3.5/doc/luac.1
lua-5.3.5/doc/manual.html
lua-5.3.5/doc/manual.css
lua-5.3.5/doc/contents.html
[...]
lua-5.3.5/doc/readme.html
lua-5.3.5/src/
lua-5.3.5/src/ldblib.c
lua-5.3.5/src/lmathlib.c
lua-5.3.5/src/loslib.c
lua-5.3.5/src/lvm.c
lua-5.3.5/src/ldo.h
lua-5.3.5/src/lua.h
[...]
lua-5.3.5/src/lua.hpp
[...]
lua-5.3.5/README
[...]

Change into the directory "~/tmp/lua/lua-5.3.5" in order to build the interpreter.

$> cd ~/tmp/lua/lua-5.3.5

Compile the Lua interpreter from the sources


In order to check how the interpreter can be build and to get more information, we type "make"

$> make

Please do 'make PLATFORM' where PLATFORM is one of these:
aix bsd c89 freebsd generic linux macosx mingw posix solaris
See doc/readme.html for complete instructions.

For further explanations, we can check the included documentation in "doc/readme.html".

Let's compile the sources for the Linux target system.

$> make linux

cd src && make linux
make[1]: Entering directory '/home/cschmidt/tmp/lua/lua-5.3.5/src'
make all SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline"
make[2]: Entering directory '/home/cschmidt/tmp/lua/lua-5.3.5/src'
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_USE_LINUX -c -o lapi.o lapi.c
[...]
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_USE_LINUX -c -o linit.o linit.c
ar rcu liblua.a lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o
ar: `u' modifier ignored since `D' is the default (see `U')
ranlib liblua.a
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_USE_LINUX -c -o lua.o lua.c
lua.c:82:10: fatal error: readline/readline.h: No such file or directory
#include
^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
: recipe for target 'lua.o' failed
make[2]: *** [lua.o] Error 1
make[2]: Leaving directory '/home/cschmidt/tmp/lua/lua-5.3.5/src'
Makefile:110: recipe for target 'linux' failed
make[1]: *** [linux] Error 2
make[1]: Leaving directory '/home/cschmidt/tmp/lua/lua-5.3.5/src'
Makefile:55: recipe for target 'linux' failed
make: *** [linux] Error 2

Ooops, that was unexpected!

However, a quick online research shows that in order to compile Lua the dependency to the "readline" library has to be met.
Let's quickly resolve that.

$> sudo apt-get install libreadline-dev

Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
libtinfo-dev
Suggested packages:
readline-doc
The following NEW packages will be installed:
libreadline-dev libtinfo-dev
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 214 kB of archives.
After this operation, 1.134 kB of additional disk space will be used.
Do you want to continue? [J/n] J
Get:1 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 libtinfo-dev amd64 6.1-1ubuntu1.18.04 [81,3 kB]
Get:2 http://archive.ubuntu.com/ubuntu bionic/main amd64 libreadline-dev amd64 7.0-3 [133 kB]
Fetched 214 kB in 0s (557 kB/s)
Selecting previously unselected package libtinfo-dev:amd64.
(Reading database ... 354931 files and directories currently installed.)
Preparing to unpack .../libtinfo-dev_6.1-1ubuntu1.18.04_amd64.deb ...
Unpacking libtinfo-dev:amd64 (6.1-1ubuntu1.18.04) ...
Selecting previously unselected package libreadline-dev:amd64.
Preparing to unpack .../libreadline-dev_7.0-3_amd64.deb ...
Unpacking libreadline-dev:amd64 (7.0-3) ...
Processing triggers for install-info (6.5.0.dfsg.1-2) ...
Setting up libtinfo-dev:amd64 (6.1-1ubuntu1.18.04) ...
Setting up libreadline-dev:amd64 (7.0-3) ...

And try again ...

$> make linux

cd src && make linux
make[1]: Entering directory '/home/cschmidt/tmp/lua/lua-5.3.5/src'
make all SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline"
make[2]: Entering directory '/home/cschmidt/tmp/lua/lua-5.3.5/src'
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_USE_LINUX -c -o lua.o lua.c
gcc -std=gnu99 -o lua lua.o liblua.a -lm -Wl,-E -ldl -lreadline
gcc -std=gnu99 -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_USE_LINUX -c -o luac.o luac.c
gcc -std=gnu99 -o luac luac.o liblua.a -lm -Wl,-E -ldl -lreadline
make[2]: Leaving directory '/home/cschmidt/tmp/lua/lua-5.3.5/src'
make[1]: Leaving directory '/home/cschmidt/tmp/lua/lua-5.3.5/src'

Done.

In order to install everything system-wide, you can now type

$> sudo make linux install

But hold on!
Do we really want to pollute our system and install things system-wide without having the possibility to uninstall safely everything later?

What about just create a local install for the current user ...

$> make local

make install INSTALL_TOP=../install
make[1]: Entering directory '/home/cschmidt/tmp/lua/lua-5.3.5'
cd src && mkdir -p ../install/bin ../install/include ../install/lib ../install/man/man1 ../install/share/lua/5.3 ../install/lib/lua/5.3
cd src && install -p -m 0755 lua luac ../install/bin
cd src && install -p -m 0644 lua.h luaconf.h lualib.h lauxlib.h lua.hpp ../install/include
cd src && install -p -m 0644 liblua.a ../install/lib
cd doc && install -p -m 0644 lua.1 luac.1 ../install/man/man1

Let's see, what this did:

$> ls -la

drwxr-xr-x 5 cschmidt cschmidt 4096 Jun 19 21:43 .
drwxrwxr-x 3 cschmidt cschmidt 4096 Jun 19 21:35 ..
drwxr-xr-x 2 cschmidt cschmidt 4096 Jun 26 2018 doc
drwxrwxr-x 7 cschmidt cschmidt 4096 Jun 19 21:43install
-rw-r--r-- 1 cschmidt cschmidt 3273 Dez 20 2016 Makefile
-rw-r--r-- 1 cschmidt cschmidt 151 Jun 26 2018 README
drwxr-xr-x 2 cschmidt cschmidt 4096 Jun 19 21:40 src

$> ls -la install

drwxrwxr-x 7 cschmidt cschmidt 4096 Jun 19 21:43 .
drwxr-xr-x 57 cschmidt users 4096 Jun 20 20:59 ..
drwxrwxr-x 2 cschmidt cschmidt 4096 Jun 19 21:43 bin
drwxrwxr-x 2 cschmidt cschmidt 4096 Jun 19 21:43 include
drwxrwxr-x 3 cschmidt cschmidt 4096 Jun 19 21:43 lib
drwxrwxr-x 3 cschmidt cschmidt 4096 Jun 19 21:43 man
drwxrwxr-x 3 cschmidt cschmidt 4096 Jun 19 21:43 share

Fine, everything is build locally into a sub-folder "install". If we want to use this version, we can just move it to our home-account and expand the "PATH" environment variable by the location to the Lua interpreter binary:

$> mv install ~/lua
$> set PATH=$PATH:~/lua/bin

In order to add the binary path permanently after a new login, we need to edit the "PATH" variable in our ".bashrc" file as we already did in some of the other articles e.g. Linux Mint: Compile and install the Go compiler from source.

Anyway, this time we want to build a Debian installer package instead.

Build a Debian package to install


As we already know from the article about Linux Mint: Linux Mint: Build your own debian package of cmake, we can use "checkinstall":

$> sudo checkinstall --install=no

checkinstall 1.6.2, Copyright 2009 Felipe Eduardo Sanchez Diaz Duran
This software is released under the GNU GPL.



*****************************************
**** Debian package creation selected ***
*****************************************

The configuration will look like something similar to

This package will be built according to these values:

0 - Maintainer: [ cschmidt@gimli ]
1 - Summary: [ Lua 5.3.0 private build ]
2 - Name: [ lua ]
3 - Version: [ 5.3.5 ]
4 - Release: [ 1 ]
5 - License: [ GPL ]
6 - Group: [ checkinstall ]
7 - Architecture: [ amd64 ]
8 - Source location: [ lua-5.3.5 ]
9 - Alternate source location: [ ]
10 - Requires: [ ]
11 - Provides: [ lua ]
12 - Conflicts: [ ]
13 - Replaces: [ ]

Enter a number to change any of them or press ENTER to continue:

so we adjust everything in order to our needs (for details see also the article Linux Mint: Linux Mint: Build your own debian package of cmake):

This package will be built according to these values:

0 - Maintainer: [ christianschmidt@hotmail.com ]
1 - Summary: [ Lua 5.3.0 private build ]
2 - Name: [ lua ]
3 - Version: [ 5.3.5 ]
4 - Release: [ 1 ]
5 - License: [ MIT ]
6 - Group: [ checkinstall ]
7 - Architecture: [ amd64 ]
8 - Source location: [ lua-5.3.5 ]
9 - Alternate source location: [ https://www.lua.org/ftp/lua-5.3.5.tar.gz ]
10 - Requires: [ ]
11 - Provides: [ lua ]
12 - Conflicts: [ ]
13 - Replaces: [ ]

Enter a number to change any of them or press ENTER to continue:

Now, we can hit "ENTER" to start the build process.

Installing with make install...

========================= Installation results ===========================
cd src && mkdir -p /usr/local/bin /usr/local/include /usr/local/lib /usr/local/man/man1 /usr/local/share/lua/5.3 /usr/local/lib/lua/5.3
cd src && install -p -m 0755 lua luac /usr/local/bin
cd src && install -p -m 0644 lua.h luaconf.h lualib.h lauxlib.h lua.hpp /usr/local/include
cd src && install -p -m 0644 liblua.a /usr/local/lib
cd doc && install -p -m 0644 lua.1 luac.1 /usr/local/man/man1

======================== Installation successful ==========================

Copying documentation directory...
./
./doc/
./doc/lua.css
./doc/contents.html
./doc/manual.css
./doc/luac.1
./doc/index.css
./doc/osi-certified-72x60.png
./doc/readme.html
./doc/lua.1
./doc/logo.gif
./doc/manual.html
./README

Copying files to the temporary directory...OK

Stripping ELF binaries and libraries...OK

Compressing man pages...OK

Building file list...OK

Building Debian package...OK

NOTE: The package will not be installed

Erasing temporary files...OK

Deleting temp dir...OK


**********************************************************************

Done. The new package has been saved to

/home/cschmidt/tmp/lua/lua-5.3.5/lua_5.3.5-1_amd64.deb
You can install it in your system anytime using:

dpkg -i lua_5.3.5-1_amd64.deb

**********************************************************************

Finished.

We now have a package "lua_5.3.5-1_amd64.deb" in the folder "~/tm/lua/lua-3.5.3" that we can e.g. double-click to install.

References:

  1. Lua homepage