luapath: Lua installation paths utility

description

luapath is a portable shell script which derives compiler flags and filesystem paths necessary to utilize Lua, LuaJIT, and particular versions thereof in both simple and mixed installation environments.

Unlike, e.g., Perl installations, the header and interpreter paths of Lua installations are exceptionally variable. Additionally, environments often contain mixed installations of Lua 5.1, 5.2, 5.3, and LuaJIT (2.0, 2.1, etc) in both standard and unstandard locations.

I include luapath with my Lua modules and their Makefiles, both in open source and proprietary projects, to ease the problem of deriving the proper compiler flags in ad hoc environments.

luapath is not a replacement for other projects such as LuaRocks or pkg-config. It's simply a script for a singular yet difficult task—discovering and distinguishing a multitude of Lua headers and interpreters. The approach taken is to embrace the chaos when you cannot dictate a particular build system or convention downstream.

news

2016-03-25

Support ${CC} values with trailing flags, which invoke the compiler through env(1), or which otherwise are intended to expand as multiple words.

OpenBSD 5.8 sh does not suppress strict errors within an eval invoked from an if condition compound-list. Workaround by changing trylua to return 0 on matching failure, like tryluainclude and tryluac do.

Undeprecate ldir and cdir. The names are more intuitive and convenient as evidenced by the fact that I keep using them instead of package.path and package.cpath. Try to maintain backwards compatibility by using a simple heuristic to differentiate lua interpreter glob patterns from preferred install directory string.match expressions.

Tag rel-20160325 (a025672fee036b1ac2d06c97295a4da7e9611d37).

2016-03-18

Fix bug in tryluac where a continue statement was used instead of return 0.

2015-07-14

Add recursive glob function implemented in shell code and use instead of find(1).

2015-01-19

Add fix for LuaJIT's default package.cpath, which tends to hardcode /usr/local/lib/lua/5.1, ordered before the LuaJIT installation prefix.

2015-01-15

Quote more command names and arguments. Still need to handle space characters in code that employs command substitution. I think we could handle all whitespace characters, including newlines, by using a control character in IFS and using --exec printf "%s\1" {} rather than -print with find(1).

2014-12-22

Fix unbound variable usage in mmp2num function.

2014-12-19

Fix pkg-config version matching. The --modversion of the lua package might be stale. For example, it's 5.2.0 on Ubuntu 14.04 even though the Lua release is 5.2.3.

Use the interpreter path as a reference point when searching for headers. $(dirname ${LUA_PATH})/../include is a very likely location as bindir and includedir have the same prefix in most installations.

2014-12-18

Add -e GLOB option.

Deprecate ldir and cdir modes.

Add package.path and package.cpath to replace ldir and dir modes. Optional arguments to the new modes are preferred install paths, rather than globs for finding the lua utility path (use the new -e option, instead).

2014-09-26

Add ldir and cdir modes for finding module install paths.

2014-01-26

Add ccname mode.

Tag rel-20140126 (fd2912e7590563285d78fcc8213ace8421c90df7).

2013-10-25

Fix luac test where printf would complain when printing to a broken pipe.

2013-10-22

Improve Linux multiarch layout and pkg-config support.

Improve performance by trying non-recursive search first.

2013-09-09

Handle bugs with NetBSD's sh implementation. First, NetBSD's +noclobber setting fails when redirecting to /dev/null, but POSIX says it should only fail if redirecting to a regular file. Second, the +nounset option fails when iterating over a null parameter set; `do X; ... done` complains about $@ being unset.

Tag rel-20130909 (30d6a6a9bb7f11d7e2052c836c83a02650aa37c0).

2013-08-30

Handle case where pkg-config exits non-0 because the pipeline didn't generate any package names to query. Because luapath enables strict errors with `set -e`, this caused the script to fail entirely when pkg-config was present without any lua packages also installed.

Tag rel-20130830 (34b046f6508298ada10c5e6d0a95b1bc1f279361).

2013-08-21

Portability fixes for Solaris.

Tag rel-20130821 (bb3a1702597e85d5e1afa8d6f1b63b7af003fef9).

2013-08-07

Add pkg-config support and refactor header probing to delay recursive searching.

Tag rel-20130807 (4ed49351280117020aa46e0f676d14e13592b151).

2013-08-05

Redirect stdin from /dev/null when probing so we don't freeze if a utility tries to read from stdin. And chdir to a read-only directory by default to try to prevent creation of temporary files. These features address the issues of LuaTeX reading from stdin and creating a luatex.out file in the current working directory. By default a directory with a random suffix generated from /dev/urandom is placed in TMPDIR and removed on exit.

If CPPFLAGS is empty and no -I options directly specified then set INCDIRS to "/usr/include:/usr/local/include".

Tag rel-20130805 (103801fe44915d5d1ad3f382b49edd68f6cd25e2).

2013-08-03

Various portability fixes. Better default search parameters.

Tag release rel-20130803 (2c7fda3072581605635db77c5eb206cdccff9119).

2013-08-02

Published project.

usage

In general luapath does little automatically. Some features needed to effectively discover and probe the system must be explicitly enabled. Most people will want to use the -r option to recurse directories, and the -x and -m options to limit the recursion. /usr/include and /usr/local/include should usually be specified explicitly using the -I option, or using the preprocessor -I option via the CPPFLAGS environment variable.

There's no single way to use the luapath script, and even my usage has evolved. Here's an example using a GNU Make template to compile a module with explicit Lua 5.1 and Lua 5.2 targets. This example allows the end user to specify header locations for both Lua 5.1 and Lua 5.2 in CPPFLAGS, although on many systems the user won't have to specify anything. It's critical in this example that luapath-generated flags are passed to the compiler before user-specified flags in CPPFLAGS, as the include directories in CPPFLAGS may not be in the necessary order to make visible the correct headers. Also note that the first command in each rule confirms that the correct version was found; if headers for the specified version could not be found the version command will evaulate to the empty string, causing the shell test command to fail.

prefix ?= /usr/local
includedir ?= $(prefix)/include

ifeq ($(shell uname -s), Darwin)
SOFLAGS ?= -bundle -undefined dynamic_lookup
else
SOFLAGS ?= -shared
endif

LUAPATH = $(shell env CPPFLAGS="$(CPPFLAGS)" ./luapath -krxm3 -I$(DESTDIR)$(includedir) -I$(includedir) -I/usr/include -I/usr/local/include -v$(1) $(2))

5.1/foo.so: foo.c
	test "5.1" = "$(call LUAPATH, 5.1, version)"
	mkdir -p -m755 $(@D)
	$(CC) -o $@ $< $(CFLAGS) $(call LUAPATH, 5.1, cppflags) $(CPPFLAGS) $(SOFLAGS) $(LDFLAGS) $(LIBS)

5.2/foo.so: foo.c
	test "5.2" = "$(call LUAPATH, 5.2, version)"
	mkdir -p -m755 $(@D)
	$(CC) -o $@ $< $(CFLAGS) $(call LUAPATH, 5.2, cppflags) $(CPPFLAGS) $(SOFLAGS) $(LDFLAGS) $(LIBS)
			

For further usage information examine the list of options and commands.

usage: luapath [-I:L:P:d:De:krm:xsv:j:JVh] cppflags|version|lua|luac|...
  -I PATH      additional search directory for includes
  -L PATH      additional search directory for libraries
  -P PATH      additional search directory for binaries
  -d PATH      use PATH as sandbox directory; a random 16 byte suffix is
               generated from /dev/urandom and the directory removed on exit
               unless a trailing "/" is present
               (default sandbox is $TMPDIR/luapath-XXXXXXXXXXXXXXXX)
  -D           do not create a sandbox
  -e GLOB      glob pattern for finding utilities (lua, luac, etc)
  -k           query pkg-config if available
  -r           recursively search directories
  -m MAXDEPTH  limit recursion to MAXDEPTH (only for GNU and BSD find)
  -x           do not cross device mounts when recursing
  -s           find shortest pathname, otherwise print first best match
  -v VERSION   require specific Lua version or range
               (e.g. "5.1" or "5.1-5.2")
  -j VERSION   require specific LuaJIT version or range
               (e.g. "2.0.1"; empty ranges like "-" force any LuaJIT version)
  -J           skip LuaJIT if encountered
  -V           print this script's version information
  -h           print this usage message

  cppflags       print derived additional CPPFLAGS necessary
  ldflags        print derived additional LDFLAGS necessary (TODO)
  version        print derived Lua API version
  luac           print path to luac utility (lua lua[5-9]* lua-[5-9]* luajit*)
  lua            print path to lua interpreter (luac luac[5-9]* luac-[5-9]*)
  package.path   print preferred module install path
  package.cpath  print preferred C module install path
  ccname         print CC name (e.g. sunpro, clang, gcc)
  evalmacro      run internal macro evaluator for debugging
  testsym        run internal library symbol reader for debugging

This utility is used to derive compiler flags and filesystem paths
necessary to utilize Lua, LuaJIT, and particular versions thereof.
On success it prints the requested information and exits with 0,
otherwise it fails with an exit status of 1.

Note that cppflags may not print anything if no additional flags are
required to compile against the requested API version.

When searching, the highest Lua version is preferred. Searching
stops once the highest version in the allowable range is found
unless the -s flag is specified.

LuaJIT is treated like any other Lua installation. If an explicit
LuaJIT version or range is specified, then only LuaJIT installations
will match. To exclude LuaJIT entirely use the -J switch.

This utility processes the environment variables CC, CPPFLAGS,
LDFLAGS, and PATH if present. If recursion is requested, then
directories specified in CPPFLAGS, LDFLAGS, and PATH are also
recursed.

If the environment variable CPPFLAGS is empty and no -I options are
specified directly, then /usr/include and /usr/local/include are
used when probing for cppflags and API version.

Report bugs to <william@25thandClement.com>
		

license

Copyright (c) 2012-2016 William Ahern

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

source

git clone http://25thandClement.com/~william/projects/luapath.git

download

luapath-20160325

runlua-20150617

other projects

airctl | bsdauth | cnippets | libmime | libarena | libevnet | authldap | streamlocal | libnostd | zoned | dns.c | delegate.c | llrb.h | lpegk | json.c | cqueues | siphash.h | hexdump.c | timeout.c | luapath | luaossl | lunix | phf | runlua | AnonNet