by Tim Caswell
Compile Luvi From Source
The pre-built luvi binaries won’t run here because they use glibc (the default libc for most linux systems.). But the good news is compiling a custom luvi is as simple as compiling from source.
Alpine has a simple package manager called apk. We’ll use it to install a few prerequisites needed to clone and build from source.
apk update # Install git and perl (needed for git submodules). apk add git perl # Install build tools. apk add build-base cmake linux-headers
Now we will build luvi from source in the normal way.
# Clone luvi source recursively to get all submodules. git clone --recursive https://github.com/luvit/luvi.git # Build luvi (use tiny instead of reqular-asm if you don't need openssl) cd luvi make regular-asm test
If all goes well this will configure, build, and then test successfully.
Let’s install luvi to a new
mkdir ~/bin install build/luvi ~/bin
…and add it to our path.
echo 'export PATH=$HOME/bin:$PATH' >> ~/.profile . ~/.profile
Building the Luvi Invention Toolkit
Normally luvi based apps like lit, luvit, and wscat are built by downloading the appropriate luvi binary and concatenating it with a zip file containing the application itself. This works because executables ignore extra data on the end and zip files ignore extra data at the front. By combining them we get a file that is both a zip file and an executable.
Lit does a little more by reading
package.lua and synthesizing the dependencies
directly into the generated zip file. Also it attempts to compile all lua files
into bytecode to save space and skip files not meant to be included. But in the
end, it’s still generating a custom zip file and then appending it to the
desired luvi binary.
Luvi can work on either a folder, a zip file, or detect a zip file appended to itself. Thus we can use lit to build itself once we have the luvi binary and the lit zip.
cd wget https://lit.luvit.io/packages/luvit/lit/latest.zip
We can now run lit from the zip file by doing
luvi latest.zip -- args....
Everything before the
-- in luvi is the source trees/zips, everything after is
arguments to pass to the app itself.
make source_app target_binary custom_luvi command we can built lit
using our custom luvi.
luvi latest.zip -- make latest.zip ~/bin/lit ~/bin/luvi
Sharing Luvi Across Apps
But keeping with the spirit of Alpine and BusyBox, BusyBox is a single binary
where commands like
cat, etc are just symlinks pointing to the
same file, we want to share the same luvi binary across all our luvi-based apps.
If you look at the built
lit file in
~/bin, you’ll see it’s just slightly
bigger than the
luvi binary itself.
> du -h ~/bin/* 4.7M /root/bin/lit 4.5M /root/bin/luvi
It turns out this is quite possible. I added a feature to luvi a while back
where if there are no arguments before the
-- separator, it will consume one
source path after it. This means you can replace the 4.5 megabyte header with
a single line
Let’s save that line to a file so that it can take the place of our custom luvi path.
echo '#!/root/bin/luvi --' > prefix # Make sure to use the path to *your* luvi.
Now let’s rebuild lit using this custom luvi. Also now that we have lit bootstrapped, we can build the normal way from the repository.
lit make lit://luvit/lit ~/bin/lit prefix
Now we have a much smaller lit.
244.0K /root/bin/lit 4.5M /root/bin/luvi
We can install any other luvi-based apps in the same way now.
lit make lit://luvit/luvit ~/bin/luvit prefix lit make lit://creationix/wscat ~/bin/wscat prefix lit make lit://creationix/simple-http-server ~/bin/simple-http-server prefix lit make lit://virgo-agent-toolkit/fife ~/bin/fife prefix ...