summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2023-12-29 21:46:06 +0100
committerAki <please@ignore.pl>2023-12-29 21:46:06 +0100
commit178348d704a6186d8ed0485b7909ee9bd5b9ff9d (patch)
treed87adf475c7bd387c404185673ea4ce37380cc76
parent8498e2adddad3dc9068bb91436d3eefae6fcbe6f (diff)
downloadignore.pl-178348d704a6186d8ed0485b7909ee9bd5b9ff9d.zip
ignore.pl-178348d704a6186d8ed0485b7909ee9bd5b9ff9d.tar.gz
ignore.pl-178348d704a6186d8ed0485b7909ee9bd5b9ff9d.tar.bz2
Published how to install lua thingy
-rw-r--r--how_to_write_install_targets_for_lua_modules_in_makefiles-1.pngbin0 -> 4715 bytes
-rw-r--r--how_to_write_install_targets_for_lua_modules_in_makefiles-2.pngbin0 -> 5723 bytes
-rw-r--r--how_to_write_install_targets_for_lua_modules_in_makefiles.html312
-rw-r--r--index.html3
4 files changed, 315 insertions, 0 deletions
diff --git a/how_to_write_install_targets_for_lua_modules_in_makefiles-1.png b/how_to_write_install_targets_for_lua_modules_in_makefiles-1.png
new file mode 100644
index 0000000..0a4bed2
--- /dev/null
+++ b/how_to_write_install_targets_for_lua_modules_in_makefiles-1.png
Binary files differ
diff --git a/how_to_write_install_targets_for_lua_modules_in_makefiles-2.png b/how_to_write_install_targets_for_lua_modules_in_makefiles-2.png
new file mode 100644
index 0000000..41f85ae
--- /dev/null
+++ b/how_to_write_install_targets_for_lua_modules_in_makefiles-2.png
Binary files differ
diff --git a/how_to_write_install_targets_for_lua_modules_in_makefiles.html b/how_to_write_install_targets_for_lua_modules_in_makefiles.html
new file mode 100644
index 0000000..a43b259
--- /dev/null
+++ b/how_to_write_install_targets_for_lua_modules_in_makefiles.html
@@ -0,0 +1,312 @@
+<!doctype html>
+<html lang="en">
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<meta name="author" content="aki">
+<meta name="tags" content="lua, module, make, install, target, installation">
+<meta name="published-on" content="2023-12-29T21:45:00+01:00">
+<link rel="icon" type="image/png" href="favicon.png">
+<link rel="stylesheet" href="style.css">
+<style>
+.comment { color: #2552d7; }
+.explanation {
+ height: fit-content;
+ border-collapse: collapse;
+}
+.explanation td {
+ height: 100%;
+ padding: 0;
+}
+.explanation td > div {
+ height: 100%;
+ display: flex;
+ box-sizing: border-box;
+ flex-direction: column;
+}
+.explanation td > div > * { flex-grow: 1; }
+.explanation td > *, .explanation td > div > * { margin-top: 0; }
+.explanation td > *:last-child, .explanation td > div > *:last-child { margin-bottom: 0; }
+.explanation td.description { padding: 0.6em 1em; }
+</style>
+
+<title>How to Write Install Targets for Lua Modules in Makefiles</title>
+
+<nav><p><a href="https://ignore.pl">ignore.pl</a></p></nav>
+
+<article>
+<h1>How to Write Install Targets for Lua Modules in Makefiles</h1>
+<p class="subtitle">Published on 2023-12-29 21:45:00+01:00
+<p>You can skip the full context and go right to the <a href="#proposition">explanation of the proposed makefile</a>.
+<p>"Installation" can mean two things: installing packages using package manager (e.g., <b>pacman</b>(8), <b>apt</b>(8))
+or copying files from one spot to another. Of course, package managers may copy files during the installation process,
+but in the latter case I mean <em>only</em> copying and maybe creating destination directories.</p>
+<img src="how_to_write_install_targets_for_lua_modules_in_makefiles-1.png" alt="simplified pigeon installation process">
+<p>The usual encounter goes like: download some sources, build them, run checks, then run as is or <em>install</em> to
+<code>/usr/local</code> to make it available system-wide and then run.
+<p>With <b>make</b>(1) it's like:
+<pre>
+$ make
+$ make test <span class="comment"># or: check</span>
+# make install
+</pre>
+<p>We might see many different installation targets, but if there's any, <code>install</code> should be one of them.
+These targets conventionally use several variables to change their behaviour. Among those we can see:
+<pre>
+DESTDIR=
+PREFIX=/usr/local
+BINDIR=$(PREFIX)/bin
+LIBDIR=$(PREFIX)/lib
+INCLUDEDIR=$(PREFIX)/include
+DATADIR=$(PREFIX)/share
+MANDIR=$(DATADIR)/man
+MAN1DIR=$(MANDIR)/man1
+</pre>
+<p>When we run <code>make PREFIX=/usr install</code>, the <code>PREFIX</code> will change to <code>/usr</code> and so
+will all downstream directories. Note that nothing uses <code>DESTDIR</code> yet. <code>DESTDIR</code> is used for
+staging the files with their intended structure before they make it to the real target location. This is commonly used
+by package maintainers along with <b>fakeroot</b>(1) or similar method.
+<p>For more details about these paths consult
+<a href="https://refspecs.linuxfoundation.org/FHS_3.0/index.html">Filesystem Hierarchy Standard</a>, <b>hier</b>(7),
+<b>file&#8209;hierarchy</b>(7) and system specific documentation. For more information about names of the variables see
+<a href="https://www.gnu.org/software/make/manual/html_node/Standard-Targets.html">Standard Targets for Users</a> and
+<a href="https://www.gnu.org/software/make/manual/html_node/Directory-Variables.html">Variables for Installation
+Directories</a> from GNU Make documentation.
+<p>Now consider a simple target definition:
+<pre>
+install: all
+ install -m644 -Dt $(DESTDIR)$(INCLUDEDIR) include/*.h
+ install -m755 -Dt $(DESTDIR)$(LIBDIR) libuseful.so.1.0.0
+ ln -s $(DESTDIR)$(LIBDIR)/libuseful.so.1.0.0 $(DESTDIR)$(LIBDIR)/libuseful.so.1
+ ln -s $(DESTDIR)$(LIBDIR)/libuseful.so.1 $(DESTDIR)$(LIBDIR)/libuseful.so
+</pre>
+<p>Note the <code>$(DESTDIR)</code> use.
+<p>First we copy all header files then the shared library. Here I use <b>install</b>(1), but a combination of
+<b>mkdir</b>(1), <b>cp</b>(1) and <b>chmod</b>(1) would create an equivalent result. I also make some specific-version
+symbolic links for the library. Variables to hold filenames and the version could be used. They are omitted to limit
+scope of the example.
+<p>What about Lua?
+<p>Even with standards, conventions, recommendations makefiles in the wild have a lot of variation. For Lua there are no
+conventions around, so we will see even more variation among the projects. I want to respect this variation when
+proposing an install target for a Lua project. Let's take a look.
+<p>I selected a set of projects available in arch package repository, took a look upstream, took a look at PKGBUILDs,
+searched some more through Github. From that I identified four groups of interest:
+<ul>
+<li>Projects that leave the entire installation process to the user (e.g., LPeg or any one-file Lua module).
+<li>Projects that have makefile with <code>install</code> target or equivalent (we're interested in these).
+<li>
+ Projects that have rockspec files and rely on Luarocks builtin installation handling or equivalent (e.g., Penlight,
+ Busted).
+<li>Projects that have other (Luke, CMake) or hybrid installation definitions (LuaRocks+sth) (e.g., luaposix, luasdl2).
+</ul>
+<p>Some projects had both makefiles and rockspecs (using builtin build type). I did not try to dig out why, but I guess
+it was either: migration to rockspec, developer preference, or similar. Another scenario are projects that did not have
+their own rockspec got one written by a package maintainer for LuaRocks (since it's required) or distro-specific package
+repository (due to preference). These kind of rockspecs could get merged to the upstream project.
+<p>From projects with makefiles I selected:
+<ul>
+<li>
+ <a href="https://github.com/alerque/cldr-lua/blob/master/Makefile">cldr-lua</a>, shamelessly uses luarocks in
+ <code>install</code> target.
+<li>
+ <a href="https://github.com/mascarenhas/cosmo/blob/master/Makefile">cosmo</a>, <code>LUA_DIR</code> and
+ <code>LUA_LIBDIR</code>.
+<li>
+ <a href="https://github.com/luarocks/luarocks/blob/master/GNUmakefile">LuaRocks</a>, <code>luadir</code>, which is
+ inline with their recommendation.
+<li>
+ <a href="https://github.com/lunarmodules/luaexpat/blob/master/Makefile">luaexpat</a>, <code>LUA_V</code> with
+ <code>LUA_LDIR</code> and <code>LUA_CDIR</code>.
+<li>
+ <a href="https://github.com/LuaLanes/lanes/blob/master/Makefile">lanes</a>, <code>LUA_SHAREDIR</code> and
+ <code>LUA_LIBDIR</code>
+<li>
+ <a href="https://github.com/lgi-devs/lgi/blob/master/lgi/Makefile">lgi/lgi</a>, same names with addition of
+ <code>LUA_VERSION</code>
+<li><a href="https://github.com/hoelzro/lua-repl/blob/main/Makefile">lua-repl</a>, :)
+<li>
+ <a href="https://github.com/libmpack/libmpack-lua/blob/master/Makefile">libmpack-lua</a>, rather unique
+ <code>LUA_CMOD_INSTALLDIR</code>.
+<li>
+ <a href="https://github.com/Lua-cURL/Lua-cURLv3/blob/master/Makefile">Lua-cURLv3</a>, <code>LUA_VERSION</code> with
+ <code>LUA_LMOD</code> and <code>LUA_CMOD</code>
+<li>
+ <a href="https://github.com/lunarmodules/luasocket/blob/master/src/makefile">luasocket</a>, <code>LUAV</code> with
+ <code>LDIR</code> and <code>CDIR</code>.
+<li>
+ <a href="https://github.com/o-lim/luasystem/blob/master/src/Makefile">luasystem</a>, same but
+ <code>LUA_VERSION</code>.
+<li>
+ <a href="https://github.com/hoelzro/lua-term/blob/master/Makefile">lua-term</a>, <code>LUA_VER</code> with
+ <code>LUA_SHARE</code> and <code>LUA_LIBDIR</code>
+<li>
+ <a href="https://framagit.org/fperrad/lua-TestMore/-/blob/master/Makefile">lua-TestMore</a>, <code>LUAVER</code>
+ with <code>LIBDIR</code> and nothing for shared libraries
+</ul>
+<p>How are these makefiles used when their parent project is packaged for different OS distributions? Well, each
+distribution has its own packaging processes. Let's take a quick look at two.</p>
+<img src="how_to_write_install_targets_for_lua_modules_in_makefiles-2.png" alt="luarocks illusionary logo">
+<p>Debian/Ubuntu in case of Lua packages will not use them. They have <b>dh</b>(1) and <b>dh_lua</b>(1) which together
+take care of the packaging process. We could try to take a look at the helper scripts, but at the time of writing they
+didn't appear helpful for this article.
+<p>Arch Linux and its PKGBUILDs for lua packages prefer to use LuaRocks to support package making. In some cases if a
+makefile from an upstream project was close enough to a conventional makefile, it could and was used. However, at least
+one package maintainer later on judged that it's simply easier to use LuaRocks for everything and even recommended
+writing rockspecs if not present upstream. Despite that there's a number of packages that simply copy things around
+since the upstream projects did not have makefiles, install targets or rockspecs.
+<p>I think this is enough information to make decisions. I also looked at some CMakeFiles and pkg-configs.
+<p>Let's set goals. Our makefiles and <code>install</code> targets must be:
+<ul>
+<li>Simple; they must be readable and understandable, so they can be used and trusted.
+<li>Generic; they must be able to work under slightly (or more) different path conventions of different distributions.
+<li>
+ Targeted; they must build and install our software for only one version of Lua but they need to support choosing
+ what that version it is (there was an interesting pattern in Arch PKGBUILDs where none of the multi-version builds
+ were used). Switching between versions must be simple.
+<li>Consistent; they must be similar to other makefiles, Lua and beyond, we have a decent set of samples to attempt it.
+<li>
+ No duplication; you know me, they must have exactly one set of unique variables that affect all targets, i.a., not
+ split between build and install stages. Of course, this might backfire in cross-compilation or another similar
+ context.
+</ul>
+
+
+<h2 id="proposition">Proposition</h2>
+<p>There's a shorter version better suited for closer inspection and copying <a href="#makefile">below</a>.
+<table class="explanation">
+<!-- This table is the ugliest HTML thing I did in a while. -->
+<tr><td><div><pre>
+LUA_VERSION=<u>5.4</u>
+</pre></div>
+<td class="description">
+<p>The first or second spot seems fitting for the version. Before build definitions, too.
+<p>I couldn't decide. Full name seems the best. I was thinking about <code>LUAVERSION</code> quite a lot since I was
+using it for my projects. In the end underscore is consistent with Lua's <code>LUA_PATH</code> variables. Shorter
+variants like <code>LUAV</code> seem to create an impression of a library or utility name (e.g., luvit/luv,
+guidanoli/luav).
+<p>Change your default value from <code><u>5.4</u></code> as necessary.
+<tr><td><div><pre>
+PREFIX=/usr/local
+<td class="description">
+<p>The first spot rival. It lost because it wouldn't need to appear before build definitions.
+<p>It defines the base path for everything else. Do not mistake or mix it with <code>DESTDIR</code>. The default value
+rarely changes, to understand it better consult sources listed somewhere above.
+<tr><td><div><pre>
+BINDIR=$(PREFIX)/bin
+LIBDIR=$(PREFIX)/lib
+DATADIR=$(PREFIX)/share
+MANDIR=$(DATADIR)/man
+MAN1DIR=$(MANDIR)/man1
+</pre></div>
+<td class="description">
+<p>Not-Lua-specific install directories. Like before I skipped some since there's only a low chance of using them.
+<p>We want these for consistency and to allow users do more granular path injection, e.g., <code>LIBDIR</code> with a
+platform triplet.
+<tr><td><div><pre>
+LUA_CMOD=$(LIBDIR)/lua/$(LUA_VERSION)
+LUA_LMOD=$(DATADIR)/lua/$(LUA_VERSION)
+</pre></div>
+<td class="description">
+<p>These are the target locations respectively for shared library and script Lua modules.
+<p>These names slowly grow in me every time I review the article. They read nicely: "<code>C</code> language, so
+library, <code>MOD</code>-ules for <code>LUA</code>" and similarly "pure <code>L</code>ua" or "<code>L</code>ua, so
+pure". These are used mainly by pkg-config files (e.g., Arch Linux, homebrew, chromebrew) and sometimes in projects.
+<p>Another candidate for pure modules was <code>LUADIR</code> which is the most popular and recommended by LuaRocks but
+it is conflicting with the same name pointing at Lua include files (e.g., LPeg uses it like this). A candidate for
+library modules <code>LUA_LIBDIR</code> has the exact same problem (this one is even worse, because it reads as
+"<code>LIBDIR</code> for <code>LUA</code>).
+<p>One concern I still think about is the broken parallel between <code>LUA_LMOD</code>/<code>LUA_CMOD</code> and
+<code>LUA_PATH</code>/<code>LUA_CPATH</code>.
+<tr><td><div><pre>
+LUA_CFLAGS=\
+ `pkg-config \
+ --cflags \
+ lua$(LUA_VERSION)`
+LUA_LDLIBS=\
+ `pkg-config \
+ --libs \
+ lua$(LUA_VERSION)`
+</pre></div>
+<td class="description">
+<p>If you need to compile some modules you will need these. I'm lazy and prefer to use <b>pkg-config</b>(1). It nicely
+cooperates with the version variable allowing to meet the simple version switching goal.
+<p>Now, since <b>pkg-config</b> is used rather than just writing things by hand, a question appears. More than one
+actually, since a simple <code>CFLAGS</code> creates multiple questions about customization (some are answered by e.g.,
+<code>+=</code>), defaults, optimization. However, I don't think this is the time to discuss them.
+<p>Here, I only wanted to point out that <code>LUA_VERSION</code> can and most likely should be reused when getting Lua
+versioned include directories.
+<p>Lines are broken for the sake of the column width, readability of this page and to save me from tweaking the style
+more than I need, since I can get lost in an endless loop of moving elements by one pixel in random directions.
+<tr><td><div><pre>
+export LUA_PATH=<u>\</u>
+ <u>$(PWD)/src/?.lua;\</u>
+ <u>$(PWD)/src/?/init.lua;;</u>
+export LUA_CPATH=<u>;;</u>
+</pre></div>
+<td class="description">
+<p>Occasionally, we may need to execute some Lua code as part of our makefile and use some of our code.
+<p><code>export</code> is not yet part of POSIX, so workaround it with shell or <b>env</b>(1).
+<p><code>LUA_CPATH</code> is an almost no-op for the sake of appearance.
+<tr><td><div><pre>
+LUA=lua
+</pre></div>
+<td class="description">
+<p>Traditionally executed commands have their own variables (btw. they are also called macros). This adds just another
+opportunity to modify them since make already runs in some environment that can be tweaked. Still, it can be useful for
+e.g., injecting <code>LUA_PATH</code> mentioned above.
+</table>
+<p>I had to break the two column view for the last part, because it would look comically. Installation target itself:
+<pre>
+install: all
+ install -m755 -Dt $(DESTDIR)$(BINDIR) wrap
+ install -m644 -Dt $(DESTDIR)$(MAN1DIR) wrap.1
+ install -m755 -Dt $(DESTDIR)$(LUA_CMOD) useful.so
+ install -m644 -Dt $(DESTDIR)$(LUA_LMOD)/wrap wrap/*.lua
+</pre>
+<p>This assumes that:
+<ul>
+<li>Build produces an executable <code>wrap</code> and shared library Lua module <code>useful.so</code> in the same
+directory makefile resides in.
+<li>There's a <code>wrap/</code> subdirectory that contains pure Lua modules that require installation.
+<li>There's <code>wrap.1</code> manpage in the makefile directory.
+</ul>
+<p>I adjusted two of my unfinished projects to use this convention, so that you can see a makefile without this kind of
+assumptions. See <a href="https://git.ignore.pl/activity/tree/Makefile">activity</a> and
+<a href="https://git.ignore.pl/lua-srcinfo/tree/Makefile">srcinfo</a>.
+<p>As an alternative to direct use of <b>install</b>(1) and to increase control over commands executed with make see
+<a href="https://www.gnu.org/software/make/manual/html_node/Command-Variables.html">Variables for Specifying
+Commands</a>.
+<p>Finally, the short version of the makefile:
+<pre id="makefile">
+LUA_VERSION=5.4
+
+PREFIX=/usr/local
+BINDIR=$(PREFIX)/bin
+LIBDIR=$(PREFIX)/lib
+DATADIR=$(PREFIX)/share
+MANDIR=$(DATADIR)/man
+MAN1DIR=$(MANDIR)/man1
+LUA_CMOD=$(LIBDIR)/lua/$(LUA_VERSION)
+LUA_LMOD=$(DATADIR)/lua/$(LUA_VERSION)
+
+LUA_CFLAGS=`pkg-config --cflags lua$(LUA_VERSION)`
+LUA_LDLIBS=`pkg-config --libs lua$(LUA_VERSION)`
+CFLAGS=$(LUA_CFLAGS)
+LDLIBS=$(LUA_LDLIBS)
+
+
+all:
+ touch wrap useful.so
+
+
+install: all
+ install -m755 -Dt $(DESTDIR)$(BINDIR) wrap
+ install -m644 -Dt $(DESTDIR)$(MAN1DIR) wrap.1
+ install -m755 -Dt $(DESTDIR)$(LUA_CMOD) useful.so
+ install -m644 -Dt $(DESTDIR)$(LUA_LMOD)/wrap wrap/*.lua
+</pre>
+<p>I still think I would prefer them without the underscores, but then <code>LUALMOD</code> would be one letter away
+from <code>LUAMOD</code> which would be annoying to deal with since it sounds like it would hold a name of a module.
+<p>What do you think? What do you use yourself (other than LuaRocks)? Do you like the two column code view thing? Until
+I create some proper feedback channel, just feel free to <a href="mailto:please@ignore.pl">send me an email</a>!
+</article>
+<script src="https://stats.ignore.pl/track.js"></script>
diff --git a/index.html b/index.html
index 8e33947..e06a78e 100644
--- a/index.html
+++ b/index.html
@@ -39,6 +39,9 @@ software and hardware engineering. I post here my projects, experiments, and wha
<h2>Posts</h2>
<p><a href="atom.xml">Atom feed</a>
<ul>
+<li> <a href="how_to_write_install_targets_for_lua_modules_in_makefiles.html">How to Write Install Targets for Lua
+ Modules in Makefiles</a><br>
+ <time>2023-12-29</time>
<li> <a href="self_update_end_of_year_2023.html">Self Update: End of Year 2023</a><br>
<time>2023-12-27</time>
<li> <a href="alcohol_of_the_year_2022.html">Alcohol of the Year 2022</a><br>