Thursday, July 11, 2019

Windows 10: Compile the Lua interpreter from source and install it for the local user

Objective


Compile the latest version of the Lua language interpreter from source (in this case version 5.3.5). Build a locally installed Lua interpreter for the current user only, in order to have the possibility to safely remove it when necessary.

Motivation


As I already mentioned in my previous post "Linux Mint: Compile the Lua interpreter from source and build your own Debian package to install it", I wanted to have a scripting language that smoothly can be integrated and combined with C++. I figured that Lua would be very handy for that job. This time, I didn't just want to have the language interpreter build for my main operating system, which is Linux Mint, but also for Windows 10. I wanted to have the installation build from the same sources for both operating systems. This article describes the process to get a local portable installation of the Lua interpreter on per user basis. It tries to describe how to compile your own Lua interpreter on Windows 10 using the (command line interface) CLI compiler from Microsoft e.g. Visual Studio 2019 Community Edition.

Prerequisites


  • Windows 10 (64 Bit)
  • Microsoft Visual Studio 2019

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 that "tmp" folder.

Get the latest source of the Lua interpreter from their homepage


Open a cmd shell, by right-clicking the Windows icon in the lower-left corner of your screen. Select "Run" from the context-menu and type "cmd".
You should get a command shell, where the current directory is already your home-directory, but to be sure, navigate to that location and create the sub-directories "tmp\lua" by typing:

$> cd %HOMEDRIVE%\%HOMEPATH%
$> mkdir tmp\lua
$> cd tmp\lua

To see, where "%HOMEDRIVE%\%HOMEPATH%" is pointing to, type in your cmd-shell:

$> echo %HOMEDRIVE%\%HOMEPATH%

C:\Users\cschmidt>

Now, open your preferred browser and navigate to the Lua FTP download page. Download the latest version of thte source code, and save it in your home-directory under the newly created folder "%HOMEDRIVE%\%HOMEPATH%\tmp\lua". Im my case the current source package of Lua was "lua-5.3.5.tar.gz".

Now you have to unpack the newly downloaded package "lua-5.3.5.tar.gz" into the "tmp\lua" folder. I am not sure if the standard Window 10 unzip mechanism is able to unpack archives packed by "*.tar.gz" compression, which usually is used on *nix-like systems e.g. Linux. I recommend to install an archive manager like 7-Zip anyway.

Once you have successfully unpacked the "lua-5.3.5.tar.gz" source code package, you should get an additional directory named "lua-5.3.5" within your "tmp\lua" folder. If you just have an intermediate file called "lua-5.3.5.tar", you have to unpack that file again.

$> dir

Directory of C:\Users\cschmidt\tmp\lua

11.07.2019 14:19 <DIR> .
11.07.2019 14:19 <DIR> ..
26.06.2018 18:21 <DIR> lua-5.3.5
21.06.2019 15:11 303.543 lua-5.3.5.tar.gz
1 File(s) 303.543 bytes
3 Dir(s) 160.112.115.712 bytes free

Everything from the source code package will be unpacked into the sub-directory "lua-5.3.5"
To see, what we got, type:

$> cd lua-5.3.5
$> dir /s

Volume in drive C has no label.
Volume Serial Number is 62D3-5614

Directory of C:\Users\cschmidt\tmp\lua\lua-5.3.5

[...]

Directory of C:\Users\cschmidt\tmp\lua\lua-5.3.5\doc

[...]

Directory of C:\Users\cschmidt\tmp\lua\lua-5.3.5\src

11.07.2019 14:53 <DIR> .
11.07.2019 14:53 <DIR> ..
06.12.2017 20:35 31.352 lapi.c
19.04.2017 19:20 545 lapi.h
19.04.2017 19:20 30.495 lauxlib.c
19.04.2017 19:20 8.632 lauxlib.h
[...]
19.04.2017 19:20 1.305 lualib.h
19.04.2017 19:20 6.179 lundump.c
19.04.2017 19:20 803 lundump.h
19.04.2017 19:29 7.075 lutf8lib.c
19.04.2017 19:39 44.393 lvm.c
19.04.2017 19:20 3.685 lvm.h
19.04.2017 19:20 1.365 lzio.c
19.04.2017 19:20 1.481 lzio.h
25.06.2018 19:46 6.911 Makefile
63 File(s) 694.458 bytes

Total Files Listed:
75 File(s) 1.088.257 bytes
8 Dir(s) 160.102.793.216 bytes free

Compile the Lua interpreter from the sources


In order to compile the Lua interpreters source code, we need a compiler. I assume that you have already a "Visual Studio 2019" (Community Edition will be sufficient) or similar installed.

We now need a new command shell with the compiler tool chain set up. The easiest way, to get this "special" shell, is to start up Visual Studio and launch the command shell from the menu:
"Tools --> Visual Studio Command Prompt"

In that shell, navigate again to our source code folder:

$> cd %HOMEDRIVE%\%HOMEPATH%\tmp\lua\lua-5.3.5\src

To compile the source, type:

$> cl /MD /O2 /c /DLUA_BUILD_AS_DLL *.c
$> ren lua.obj lua.o
$> ren luac.obj luac.o
$> link /DLL /IMPLIB:lua5.3.5.lib /OUT:lua5.3.5.dll *.obj
$> link /OUT:lua.exe lua.o lua5.3.5.lib
$> lib /OUT:lua5.3.5-static.lib *.obj
$> link /OUT:luac.exe luac.o lua5.3.5-static.lib

Alternatively, you can put all the instructions in a file named "buildLua5.3.5.bat" and just execute that file:

cl /MD /O2 /c /DLUA_BUILD_AS_DLL *.c
ren lua.obj lua.o
ren luac.obj luac.o
link /DLL /IMPLIB:lua5.3.5.lib /OUT:lua5.3.5.dll *.obj
link /OUT:lua.exe lua.o lua5.3.5.lib
lib /OUT:lua5.3.5-static.lib *.obj
link /OUT:luac.exe luac.o lua5.3.5-static.lib

$> buildLua5.3.5.bat

C:\Users\cschmidt\tmp\lua\lua-5.3.5\src>cl /MD /O2 /c /DLUA_BUILD_AS_DLL *.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.21.27702.2 for x86
Copyright (C) Microsoft Corporation. All rights reserved.

lapi.c
lauxlib.c
lbaselib.c
lbitlib.c
[...]
lua.c
luac.c
lundump.c
lutf8lib.c
lvm.c
lzio.c
Generating Code...

C:\Users\cschmidt\tmp\lua\lua-5.3.5\src>ren lua.obj lua.o

C:\Users\cschmidt\tmp\lua\lua-5.3.5\src>ren luac.obj luac.o

C:\Users\cschmidt\tmp\lua\lua-5.3.5\src>link /DLL /IMPLIB:lua5.3.5.lib /OUT:lua5.3.5.dll *.obj
Microsoft (R) Incremental Linker Version 14.21.27702.2
Copyright (C) Microsoft Corporation. All rights reserved.

Creating library lua5.3.5.lib and object lua5.3.5.exp

C:\Users\cschmidt\tmp\lua\lua-5.3.5\src>link /OUT:lua.exe lua.o lua5.3.5.lib
Microsoft (R) Incremental Linker Version 14.21.27702.2
Copyright (C) Microsoft Corporation. All rights reserved.


C:\Users\cschmidt\tmp\lua\lua-5.3.5\src>lib /OUT:lua5.3.5-static.lib *.obj
Microsoft (R) Library Manager Version 14.21.27702.2
Copyright (C) Microsoft Corporation. All rights reserved.


C:\Users\cschmidt\tmp\lua\lua-5.3.5\src>link /OUT:luac.exe luac.o lua5.3.5-static.lib
Microsoft (R) Incremental Linker Version 14.21.27702.2
Copyright (C) Microsoft Corporation. All rights reserved.

Creating library luac.lib and object luac.exp

Fine, everything is build locally into the current folder "src". If we want to use the result of this compilation, we can just move everything we need to a folder called "lua" in our home-directory:

$> mkdir %HOMEDRIVE%\%HOMEPATH%\lua
$> copy *.dll %HOMEDRIVE%\%HOMEPATH%\lua\
$> copy *.h %HOMEDRIVE%\%HOMEPATH%\lua\
$> copy *.hpp %HOMEDRIVE%\%HOMEPATH%\lua\
$> copy *.exp %HOMEDRIVE%\%HOMEPATH%\lua\
$> copy *.lib %HOMEDRIVE%\%HOMEPATH%\lua\
$> copy *.exe %HOMEDRIVE%\%HOMEPATH%\lua\

Finally we need to expand the "PATH" environment variable (in the system-settings) by that location to the Lua interpreter binary.


After doing so, we open a new command shell, as described at the beginning of this article, in order to test if everything is working:

$> lua

> Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio

To exit the interpreter, just type "CTRL-C".

Fine! Now, we can safely delete the folder "tmp\lua".

References:

  1. Lua homepage
  2. How to compile Lua 5.3.0 for Windows

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