summaryrefslogtreecommitdiff
path: root/mk/lua.path
diff options
context:
space:
mode:
authorWilliam Ahern <william@25thandclement.com>2016-06-24 21:59:02 -0700
committerWilliam Ahern <william@25thandclement.com>2016-06-24 21:59:02 -0700
commitd99465ce769657b6946190377cc8a5223f5e8261 (patch)
treed4ff546c128543fbe97dc39c8fd8ac4d2f6a3a5a /mk/lua.path
parent81bbb1fa5e14a1911cfd99f4ee791ed1e340602e (diff)
downloadluaossl-d99465ce769657b6946190377cc8a5223f5e8261.tar.gz
luaossl-d99465ce769657b6946190377cc8a5223f5e8261.tar.bz2
luaossl-d99465ce769657b6946190377cc8a5223f5e8261.zip
upgrade luapath script
Diffstat (limited to 'mk/lua.path')
-rwxr-xr-xmk/lua.path1345
1 files changed, 0 insertions, 1345 deletions
diff --git a/mk/lua.path b/mk/lua.path
deleted file mode 100755
index 8df41c9..0000000
--- a/mk/lua.path
+++ /dev/null
@@ -1,1345 +0,0 @@
1#!/bin/sh
2#
3# This script is used to derive compiler flags and filesystem paths
4# necessary to utilize Lua, LuaJIT, and particular versions thereof in both
5# simple and mixed installation environments.
6#
7# For usage help information use the -h switch.
8#
9# This script attempts to adhere strictly to POSIX shell specifications. The
10# known non-POSIX features used are the path of the shell at the very first
11# line of this script, the default compiler command name of `cc' instead of
12# `c99', and the use of /dev/urandom for generating a random sandbox
13# directory suffix. All of these can be override. For any other issues
14# please contact the author.
15#
16# WARNING: When searching for a Lua interpreter this script may execute
17# various utilities in an attempt to deduce their fitness and release
18# version. By default this script will search for and execute utilities
19# using the glob patterns luac* and lua*. But this script CANNOT GUARANTEE
20# that executing such utilities, or any other utilities, either wittingly or
21# unwittingly, will not result in your COMPUTER EXPLODING. You have been
22# warned.
23#
24# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
25#
26# Changelog:
27#
28# * 2013-08-02 - Published. Derived from an earlier script, lua.path,
29# written for the cqueues project.
30#
31# * 2013-08-05 - Redirect stdin from /dev/null when probing so we don't
32# freeze if a utility tries to read from stdin.
33#
34# chdir to a read-only directory by default to try to prevent creation
35# of temporary files. These features address the issues of LuaTeX
36# reading from stdin and creating a luatex.out file in the current
37# working directory. By default a directory with a random suffix
38# generated from /dev/urandom is placed in TMPDIR and removed on exit.
39#
40# If CPPFLAGS is empty and no -I options directly specified then set
41# INCDIRS to "/usr/include:/usr/local/include".
42#
43# * 2013-08-07 - Add pkg-config support and refactor header probing to delay
44# recursive searching.
45#
46# * 2013-09-09 - NetBSD's sh gets upset over the noclobber option and
47# redirection to /dev/null, so use append operator. And check $#
48# before iterating over a null parameter set with `do X; ... done`
49# when `set -u` is enabled--it complains about $@ being unset.
50#
51# * 2013-10-22 - Initial ldflags detection.
52#
53# * 2014-01-26 - Migrate CC vendor detection from external script.
54#
55# * 2014-09-29 - Add ldir and cdir modes which print install path by parsing
56# package.path and package.cpath.
57#
58# * 2014-12-18 - Add -e GLOB option.
59#
60# Deprecate ldir and cdir modes.
61#
62# Add package.path and package.cpath to replace ldir and dir modes.
63# Optional arguments to the new modes are preferred install paths,
64# rather than globs for finding the lua utility path (use the new -e
65# option, instead).
66#
67# * 2014-12-19 - Fix pkg-config version matching. The --modversion of
68# the lua package might be stale. For example, it's 5.2.0 on Ubuntu
69# 14.04 even though the Lua release is 5.2.3.
70#
71# Use the interpreter path as a reference point when searching for
72# headers. $(dirname ${LUA_PATH})/../include is a very likely location
73# as bindir and includedir have the same prefix in most installations.
74#
75# * 2015-01-15 - Quote more command names and arguments. Still need to
76# handle space characters in code that employs command substitution. I
77# think we could handle all whitespace characters, including newlines,
78# by using a control character in IFS and using --exec printf "%s\1" {}
79# rather than -print with find(1).
80#
81# * 2015-01-19 - Add fix for LuaJIT's default package.cpath, which tends to
82# hardcode /usr/local/lib/lua/5.1, ordered before the LuaJIT
83# installation prefix.
84#
85# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
86#
87# Copyright (C) 2012-2015 William Ahern
88#
89# Permission is hereby granted, free of charge, to any person obtaining a
90# copy of this software and associated documentation files (the "Software"),
91# to deal in the Software without restriction, including without limitation
92# the rights to use, copy, modify, merge, publish, distribute, sublicense,
93# and/or sell copies of the Software, and to permit persons to whom the
94# Software is furnished to do so, subject to the following conditions:
95#
96# The above copyright notice and this permission notice shall be included in
97# all copies or substantial portions of the Software.
98#
99# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
100# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
101# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
102# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
103# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
104# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
105# DEALINGS IN THE SOFTWARE.
106#
107set -e # strict errors
108set -u # don't expand unbound variables
109set -f # disable pathname expansion
110set -C # noclobber
111\unalias -a # no command surprises
112export LC_ALL=C # no locale headaches
113unset IFS # no field splitting surprises
114: ${TMPDIR:=/tmp} # sane TMPDIR
115: ${CC:=cc}
116unset LUA_PATH || true # interferes search for module install directory
117unset LUA_CPATH || true
118
119MYVERSION=20150119
120MYVENDOR="william@25thandClement.com"
121
122
123DEVRANDOM=/dev/urandom
124SANDBOX="${TMPDIR}/${0##*/}-"
125
126CPPDIRS= # -I directories from CPPFLAGS
127INCDIRS=
128LDDIRS= # -L directories from LDFLAGS
129LIBDIRS=
130BINDIRS=
131RECURSE=no
132MAXDEPTH= # full command switch, like "-maxdepth 3", if supported
133XDEV= # do not cross device boundaries; i.e. "-xdev"
134SHORTEST= # continue searching until shortest pathname found
135PKGCONFIG= # path to pkg-config, found by `command -v` when -k option invoked
136GLOB= # -e GLOB expression for lua, luac, ldir, and cdir
137
138GLOB_LUA="lua:lua[5-9]*:lua-[5-9]*:luajit*"
139GLOB_LUAC="luac:luac[5-9]*:luac-[5-9]*"
140
141API_MIN=500
142API_MAX=999
143API_VER=
144API_DIR=
145
146JIT_REQ=
147JIT_MIN=20000
148JIT_MAX=99999
149JIT_VER=
150JIT_DIR=
151
152LIBLUA_VER=
153LIBLUA_DIR=
154LIBLUA_LIB=
155
156LIBJIT_VER=
157LIBJIT_DIR=
158LIBJIT_LIB=
159
160LUAC_PATH=
161LUAC_VER=
162
163LUA_PATH=
164LUA_VER=
165
166
167#
168# parse CPPFLAGS -I or LDFLAGS -L directories
169#
170xdirs() {
171 OPTC="${1:-I}"
172 DIRS=
173
174 set -- ${2:-}
175
176 while [ $# -gt 0 ]; do
177 case "${1}" in
178 -${OPTC})
179 shift
180
181 if [ -n "${1:-}" ]; then
182 DIRS="${DIRS}${DIRS:+:}${1}"
183 fi
184
185 ;;
186 -${OPTC}*)
187 if [ "${1}" != "-${OPTC}" ]; then
188 DIRS="${DIRS}${DIRS:+:}${1#-${OPTC}}"
189 fi
190
191 ;;
192 esac
193
194 shift
195 done
196
197 printf -- "${DIRS}"
198}
199
200idirs() {
201 xdirs "I" "${1:-}"
202}
203
204ldirs() {
205 xdirs "L" "${1:-}"
206}
207
208# count ":"-delimited substrings
209count() {
210 IFS=:
211 set -- ${1:-}
212 unset IFS
213
214 printf "$#"
215}
216
217# append to ":"-delimited string variable
218append() {
219 NAME=${1}
220 eval VALUE="\${${NAME}}"
221 shift
222
223 IFS=:
224 TMP="$*"
225
226 IFS="\n"
227 read -r "${NAME}" <<-EOF
228 ${VALUE:-}${VALUE:+:}${TMP}
229 EOF
230 unset IFS
231}
232
233#
234# evalmacro PATH MACRO [REGEX] [SUBST]
235#
236# PATH Header identifier--#include <PATH>
237# MACRO Macro identifier
238# REGEX Optional regex pattern to match macro evaluation result
239# SUBST Optional replacement expression
240#
241evalmacro() {
242 printf "#include <$1>\n[===[$2]===]\n" \
243 | "${CC:-cc}" ${CPPFLAGS:-} -E - 2>>/dev/null \
244 | sed -ne "
245 s/^.*\\[===\\[ *\\(${3:-.*}\\) *\\]===\\].*$/${4:-\\1}/
246 t Found
247 d
248 :Found
249 p
250 q
251 "
252}
253
254
255#
256# testsym PATH NAME
257#
258# Test whether global symbol NAME exists in object file at PATH. Exits with
259# 0 (true) when found, non-0 (false) otherwise.
260#
261testsym() {
262 # NOTE: No -P for OpenBSD nm(1), but the default output format is
263 # close enough. Section types always have a leading and trailing
264 # space. U section type means undefined. On AIX [VWZ] are weak
265 # global symbols. Solaris and OS X have additional symbol types
266 # beyond the canonical POSIX/BSD types, all of which are uppercase
267 # and within [A-T].
268 (nm -Pg ${1} 2>>/dev/null || nm -g 2>>/dev/null) \
269 | sed -ne '/ [A-T] /p' \
270 | grep -qE "${2}"
271}
272
273
274tryluainclude() {
275 V="$(evalmacro "${1}" LUA_VERSION_NUM '[0123456789][0123456789]*')"
276 : ${V:=0}
277
278 if [ "${1%/*}" != "${1}" ]; then
279 D="${1%/*}"
280
281 # cleanup after Solaris directory prune trick
282 if [ "${D##*/./}" != "${D}" ]; then
283 D="${D%%/./*}/${D##*/./}"
284 else
285 D="${D%/.}"
286 fi
287 else
288 D=
289 fi
290
291 [ "$V" -gt 0 -a "$V" -ge "${API_VER:-0}" ] || return 0
292
293 [ "$V" -gt "${API_VER:-0}" -o "${#D}" -lt "${#API_DIR}" -o \( "${JIT_REQ}" = "yes" -a "${JIT_VER:-0}" -lt "${JIT_MAX}" \) ] || return 0
294
295 [ "$V" -ge "${API_MIN}" -a "$V" -le "${API_MAX}" ] || return 0
296
297 if [ -n "${JIT_REQ}" ]; then
298 J="$(evalmacro "${1%%lua.h}luajit.h" LUAJIT_VERSION_NUM '[0123456789][0123456789]*')"
299 : ${J:=0}
300
301 if [ "${JIT_REQ}" = "skip" ]; then
302 [ "${J}" -eq 0 ] || return 0
303 elif [ "${JIT_REQ}" = "yes" ]; then
304 [ "$J" -ge "${JIT_VER:-0}" ] || return 0
305 [ "$J" -gt "${JIT_VER:-0}" -o "${#D}" -lt "${#JIT_DIR}" ] || return 0
306 [ "$J" -ge ${JIT_MIN} ] || return 0
307 [ "$J" -le "${JIT_MAX}" ] || return 0
308
309 JIT_VER="$J"
310 JIT_DIR="$D"
311 fi
312 fi
313
314 API_VER="$V"
315 API_DIR="$D"
316}
317
318
319#
320# foundversion
321#
322# true if found the best (maximum) possible version, false otherwise
323#
324foundversion() {
325 if [ "${API_VER:-0}" -lt "${API_MAX}" ]; then
326 return 1
327 fi
328
329 if [ "${JIT_REQ}" = "yes" -a "${JIT_VER:-0}" -lt "${JIT_MAX}" ]; then
330 return 1
331 fi
332
333 if [ "${SHORTEST}" = "yes" ]; then
334 return 1
335 fi
336
337 return 0
338}
339
340
341#
342# luapc
343#
344# wrapper around `pkg-config ... LIB`, where LIB is derived by
345# searching for all libraries with "lua" in the name that have a
346# --modversion equal to the release version printed by ${LUA_PATH} -v.
347#
348LUAPC_LIB=
349
350luapc() {
351 [ -n "${LUA_PATH}" ] || return 0
352
353 [ -n "${PKGCONFIG}" ] || return 0
354
355 # find pkg-config library name
356 if [ -z "${LUAPC_LIB}" ]; then
357 V="$("${LUA_PATH}" -v </dev/null 2>&1 | head -n1 | sed -ne 's/^Lua[^ ]* \([0123456789][0123456789]*\(\.[0123456789][0123456789]*\)*\).*/\1/p')"
358
359 [ -n "${V}" ] || return 0
360
361 V_N=$(mmp2num "${V}")
362
363 for LIB in $("${PKGCONFIG}" --list-all </dev/null 2>>/dev/null | sed -ne 's/^\(lua[^ ]*\).*/\1/p'); do
364 M="$("${PKGCONFIG}" --modversion ${LIB} || true)"
365
366 # break immediately on exact match
367 if [ "${V}" = "${M}" ]; then
368 LUAPC_LIB="${LIB}"
369
370 break
371 fi
372
373 #
374 # NOTE: On Ubuntu 14.04 pkg-config --modversion
375 # lua5.2 prints 5.2.0 even though the release
376 # version is 5.2.3 (what lua5.2 -v prints).
377 #
378 # If the major.minor components match, then
379 # tentatively use that package name.
380 #
381 M_N=$(mmp2num "${M}" 0 0 0)
382
383 if [ "$((${V_N} / 100))" -eq "$((${M_N} / 100))" ]; then
384 LUAPC_LIB="${LIB}"
385 fi
386 done
387
388 [ -n "${LUAPC_LIB}" ] || return 0
389 fi
390
391 ${PKGCONFIG} "$@" "${LUAPC_LIB}" </dev/null 2>>/dev/null || true
392}
393
394
395#
396# findinstalldir package.path|package.cpath [preferred-path ...]
397#
398findinstalldir() {
399 V_DIR=$((${LUA_VER} / 100 % 100)).$((${LUA_VER} % 100))
400
401 if [ "${1}" = "package.cpath" ]; then
402 DIR="$(luapc --variable INSTALL_CMOD)"
403 [ -n "${DIR}" ] && set -- "$@" "${DIR}"
404
405 DIR="$(luapc --variable INSTALL_LIB)"
406 [ -n "${DIR}" ] && set -- "$@" "${DIR}/lua/${V_DIR}"
407
408 DIR="$(luapc --variable libdir)"
409 [ -n "${DIR}" ] && set -- "$@" "${DIR}/lua/${V_DIR}"
410
411 DIR="$(luapc --variable prefix)"
412 [ -n "${DIR}" ] && set -- "$@" "${DIR}/lib/lua/${V_DIR}"
413
414 # LuaJIT installations tend to include
415 # /usr/local/lib/lua/5.1 as one of the first paths, ordered
416 # before the LuaJIT installation prefix, and regardless of
417 # whether there exists a /usr/local/lib/lua/5.1.
418 set -- "$@" "${LUA_PATH}/../../lib/lua/${V_DIR}"
419 set -- "$@" "${LUA_PATH}/../../lib/*/lua/${V_DIR}" # e.g. lib/x86_64-linux-gnu
420 else
421 DIR="$(luapc --variable INSTALL_LMOD)"
422 [ -n "${DIR}" ] && set -- "$@" "${DIR}"
423
424 DIR="$(luapc --variable prefix)"
425 [ -n "${DIR}" ] && set -- "$@" "${DIR}/share/lua/${V_DIR}"
426
427 # See above LuaJIT note. Although the built-in package.path
428 # usually orders the LuaJIT installation prefix first.
429 set -- "$@" "${LUA_PATH}/../../share/lua/${V_DIR}"
430 fi
431
432 ARRAY="${1}"
433 shift
434
435 if [ $# -eq 0 ]; then
436 set -- "/nonexistent" # cannot expand empty $@ on some implementations
437 fi
438
439 "${LUA_PATH}" - "$@" <<-EOF
440 --
441 -- actual pkg-config variable on Ubuntu 14.04
442 --
443 -- /usr//share/lua/5.1
444 --
445 local function fixpath(path)
446 local stack = { path:match"^/" and "" or "." }
447
448 for ent in path:gmatch"([^/]+)" do
449 if ent == ".." and #stack > 1 then
450 stack[#stack] = nil
451 elseif ent ~= "." then
452 stack[#stack + 1] = ent
453 end
454 end
455
456 return table.concat(stack, "/")
457 end
458
459 local function topattern(path)
460 if string.match(path, "*") then
461 path = string.gsub(path, "%%", "%%")
462 return string.gsub(path, "*", "[^/]+")
463 end
464 end
465
466 local dirs = { }
467
468 for dir in ${ARRAY}:gmatch"([^;?]+)/" do
469 dir = fixpath(dir)
470
471 if dir ~= "." then
472 dirs[#dirs + 1] = dir
473 end
474 end
475
476 for _, arg in ipairs{ ... } do
477 arg = fixpath(arg)
478
479 local pat = topattern(arg)
480
481 for _, dir in ipairs(dirs) do
482 if arg == dir then
483 print(dir)
484 os.exit(0)
485 elseif pat and string.match(dir, pat) then
486 print(dir)
487 os.exit(0)
488 end
489 end
490 end
491
492 if dirs[1] then
493 print(dirs[1])
494 os.exit(0)
495 else
496 os.exit(1)
497 end
498 EOF
499}
500
501
502#
503# findversion
504#
505findversion() {
506 tryluainclude "lua.h"
507
508 if foundversion; then
509 return 0
510 fi
511
512
513 # iterate through CPPFLAGS to probe different precedence
514 if [ "${API_VER:-0}" -lt "${API_MAX}" ]; then
515 IFS=:
516 set -- ${CPPDIRS}
517 unset IFS
518
519 if [ $# -gt 0 ]; then
520 for D; do
521 tryluainclude "${D}/lua.h"
522
523 if foundversion; then
524 return 0
525 fi
526 done
527 fi
528 fi
529
530
531 if [ -n "${PKGCONFIG}" ]; then
532 PKGFLAGS="$("${PKGCONFIG}" --list-all </dev/null 2>>/dev/null | sed -ne 's/^\(lua[^ ]*\).*/\1/p' | xargs -- ${PKGCONFIG} --cflags 2>>/dev/null | cat)"
533 PKGDIRS="$(idirs "${PKGFLAGS}")"
534
535 IFS=:
536 set -- ${PKGDIRS}
537 unset IFS
538
539 if [ $# -gt 0 ]; then
540 for D; do
541 tryluainclude "${D}/lua.h"
542
543 if foundversion; then
544 return 0
545 fi
546 done
547 fi
548 fi
549
550
551 IFS=:
552 set -- ${INCDIRS}
553 unset IFS
554
555 if [ $# -gt 0 ]; then
556 for D; do
557 tryluainclude "${D}/lua.h"
558
559 if foundversion; then
560 return 0
561 fi
562 done
563 fi
564
565
566 if [ "${RECURSE}" != "yes" ]; then
567 [ "${API_VER:-0}" -gt 0 ]
568 return $?
569 fi
570
571
572 # recurse into CPPDIRS
573 IFS=:
574 set -- ${CPPDIRS}
575 unset IFS
576
577 if [ $# -gt 0 ]; then
578 for D; do
579 for F in $(find "${D}" ${MAXDEPTH} ${XDEV} -name lua.h -print 2>>/dev/null); do
580 tryluainclude "${F}"
581
582 if foundversion; then
583 return 0
584 fi
585 done
586 done
587 fi
588
589
590 # recurse into INCDIRS
591 IFS=:
592 set -- ${INCDIRS}
593 unset IFS
594
595 if [ $# -gt 0 ]; then
596 for D; do
597 for F in $(find "${D}/." ${MAXDEPTH} ${XDEV} -name lua.h -print 2>>/dev/null); do
598 tryluainclude "${F}"
599
600 if foundversion; then
601 return 0
602 fi
603 done
604 done
605 fi
606
607
608 # if we can find the lua interpreter, use it as a reference for
609 # header locations.
610 if findlua; then
611 D="${LUA_PATH%/*}"
612 D="${D%/*}/include"
613
614 if [ -d "${D}" ]; then
615 for F in $(find "${D}" ${MAXDEPTH} ${XDEV} -name lua.h -print 2>>/dev/null); do
616 tryluainclude "${F}"
617
618 if foundversion; then
619 return 0
620 fi
621 done
622 fi
623 fi
624
625 [ "${API_VER:-0}" -gt 0 ]
626}
627
628
629#
630# Unlike API version checking, this is less likely to be accurately forward
631# compatible.
632#
633trylib() {
634 if ! testsym "${1}" "lua_newstate"; then
635 return 0
636 fi
637
638 V=0
639 J=0
640 D=
641 F="${1##*/}"
642 L=
643
644 if [ "${1%/*}" != "${1}" ]; then
645 D="${1%/*}"
646
647 # cleanup after Solaris directory prune trick
648 if [ "${D##*/./}" != "${D}" ]; then
649 D="${D%%/./*}/${D##*/./}"
650 else
651 D="${D%/.}"
652 fi
653 fi
654
655 L="${F#lib}"
656 L="${L%.so}"
657 L="${L%.a}"
658 L="${L%.dylib}"
659
660
661 # FIXME: need more versioning tests
662 if testsym "${1}" "lua_getfenv"; then
663 V=501
664 elif testsym "${1}" "lua_yieldk"; then
665 V=502
666 else
667 return 0
668 fi
669
670 [ "$V" -gt 0 -a "$V" -ge "${LIBLUA_VER:-0}" ] || return 0
671
672 [ "$V" -gt "${LIBLUA_VER:-0}" -o "${#D}" -lt "${#LIBLUA_DIR}" -o \( "${JIT_REQ}" = "yes" -a "${LIBJIT_VER:-0}" -lt "${JIT_MAX}" \) ] || return 0
673
674 [ "$V" -ge "${API_MIN}" -a "$V" -le "${API_MAX}" ] || return 0
675
676
677 if [ -n "${JIT_REQ}" ]; then
678 # FIXME: need more versioning tests
679 if testsym "${1}" "luaopen_jit"; then
680 J=20000
681 fi
682
683 if [ "${JIT_REQ}" = "skip" ]; then
684 [ "${J}" -eq 0 ] || return 0
685 elif [ "${JIT_REQ}" = "yes" ]; then
686 [ "$J" -ge "${LIBJIT_VER:-0}" ] || return 0
687 [ "$J" -gt "${LIBJIT_VER:-0}" -o "${#D}" -lt "${#LIBJIT_DIR}" ] || return 0
688 [ "$J" -ge ${JIT_MIN} ] || return 0
689 [ "$J" -le "${JIT_MAX}" ] || return 0
690
691 LIBJIT_VER="$J"
692 LIBJIT_DIR="$D"
693 LIBJIT_LIB="$L"
694 fi
695 fi
696
697 LIBLUA_VER="$V"
698 LIBLUA_DIR="$D"
699 LIBLUA_LIB="$L"
700}
701
702
703#
704# foundlib
705#
706# true if found the best (maximum) possible version, false otherwise
707#
708foundlib() {
709 if [ "${LIBLUA_VER:-0}" -lt "${API_MAX}" ]; then
710 return 1
711 fi
712
713 if [ "${JIT_REQ}" = "yes" -a "${LIBJIT_VER:-0}" -lt "${JIT_MAX}" ]; then
714 return 1
715 fi
716
717 if [ "${SHORTEST}" = "yes" ]; then
718 return 1
719 fi
720
721 return 0
722}
723
724
725findlib() {
726 if [ -n "${PKGCONFIG}" ]; then
727 PKGFLAGS="$("${PKGCONFIG}" --list-all </dev/null 2>>/dev/null | sed -ne 's/^\(lua[^ ]*\).*/\1/p' | xargs -- ${PKGCONFIG} --libs 2>>/dev/null | cat)"
728 PKGDIRS="$(ldirs "${PKGFLAGS}")"
729 PKGDIRS="${PKGDIRS}${PKGDIRS:+:}/lib:/usr/lib:/usr/local/lib"
730 NUMDIRS="$(count "${PKGDIRS}")"
731 PKGLIBS="$(xdirs "l" "${PKGFLAGS}")"
732 NUMLIBS="$(count "${PKGLIBS}")"
733 ALLDIRS="${PKGDIRS}${PKGLIBS:+:}${PKGLIBS}"
734
735 IFS=:
736 set -- ${ALLDIRS}
737 unset IFS
738
739 I=1
740 while [ $I -le ${NUMDIRS} ]; do
741 K=$((1 + ${NUMDIRS}))
742 while [ $K -le $# ]; do
743 findlib_L=$(eval "printf \${$I}")
744 findlib_l=$(eval "printf \${$K}")
745
746 #printf -- "I=$I K=$K $findlib_L/lib$findlib_l*.*\n"
747
748 for findlib_R in no ${RECURSE}; do
749 for findlib_lib in $(findpath "lib${findlib_l}*.*" ${findlib_R} "${findlib_L}"); do
750 trylib "${findlib_lib}"
751 done
752
753 if foundlib; then
754 return 0
755 fi
756 done
757
758 K=$(($K + 1))
759 done
760 I=$(($I + 1))
761 done
762 fi
763
764 ALLDIRS="${LDDIRS}${LDDIRS:+:}${LIBDIRS}"
765
766 IFS=:
767 set -- ${ALLDIRS}
768 unset IFS
769
770 for findlib_D; do
771 for findlib_R in no ${RECURSE}; do
772 for findlib_lib in $(findpath "liblua*.*" ${findlib_R} "${findlib_D}"); do
773 trylib "${findlib_lib}"
774 done
775
776 if foundlib; then
777 return 0
778 fi
779 done
780 done
781}
782
783
784findpath() {
785 NAME="$1"
786 WHERE="$3"
787
788 PRUNE=
789
790 if [ "${2}" = "no" ]; then
791 PRUNE="-name . -o -type d -prune -o"
792 fi
793
794 [ ${#WHERE} -gt 0 ] || return 0
795
796 IFS=:
797 set -- ${WHERE}
798 unset IFS
799
800 if [ $# -gt 0 ]; then
801 for findpath_D; do
802 find "${findpath_D}/." ${MAXDEPTH} ${XDEV} ${PRUNE} -name "${NAME}" -print 2>>/dev/null | sed -e 's/\/\.//'
803 done
804 fi
805}
806
807
808# check setuid and setgid mode
809safeperm() {
810 [ -f "$1" -a ! -u "$1" -a ! -g "$1" ]
811}
812
813
814findluac() {
815 if [ $# -eq 0 ]; then
816 IFS=:
817 set -- ${GLOB:-${GLOB_LUAC}}
818 unset IFS
819 fi
820
821 while [ $# -gt 0 ]; do
822 for F in $(findpath "${1}" no "${PATH}"; findpath "${1}" "${RECURSE}" "${BINDIRS}"); do
823 [ -x "$F" ] && safeperm "$F" || continue
824
825 V="$("$F" -v </dev/null 2>&1 | head -n1 | sed -ne 's/^Lua \([0123456789][0123456789]*\.[0123456789][0123456789]*\).*/\1/p')"
826 : ${V:=0}
827 V="$((${V%%.*} * 100 + ${V##*.} % 100))"
828
829 [ "${V}" -gt 0 -a "${V}" -ge "${LUAC_VER:-0}" ] || continue
830
831 [ "${V}" -gt "${LUAC_VER:-0}" -o "${#F}" -lt "${#LUAC_PATH}" ] || continue
832
833 [ "${V}" -ge "${API_MIN}" -a "${V}" -le "${API_MAX}" ] || continue
834
835 printf "return true" 2>>/dev/null | ${F} -p - </dev/null >>/dev/null 2>&1 || continue
836
837 LUAC_PATH="$F"
838 LUAC_VER="$V"
839
840 [ "${SHORTEST}" = "yes" -o "${LUAC_VER}" -lt "${API_MAX}" ] || break 2
841 done
842
843 shift
844 done
845
846 if [ -n "${LUAC_PATH}" -a -n "${LUAC_VER}" ]; then
847 return 0
848 else
849 return 1
850 fi
851}
852
853
854isinteger() {
855 I="${1}"
856
857 [ "${#I}" -gt 0 ] || return 1
858
859 while [ "${#I}" -gt 0 ]; do
860 if [ "${I##[0123456789]}" = "${I}" ]; then
861 return 1
862 fi
863
864 I=${I##[0123456789]}
865 done
866
867 return 0
868}
869
870
871checkints() {
872 while [ $# -gt 0 ]; do
873 if ! isinteger "${1}"; then
874 printf -- "${0##*/}: ${1}: not a number\n" >&2
875 return 1
876 fi
877
878 shift
879 done
880}
881
882
883# Only major.minor for matching LUA_VERSION_NUM in lua.h. Also, _VERSION
884# only includes major.minor.
885lua2num() {
886 M=0
887 m="${2:-0}"
888
889 IFS=.
890 set -- ${1}
891 unset IFS
892
893 M=${1:-${M}}
894 m=${2:-${m}}
895
896 checkints $M $m
897
898 printf "$((${M} * 100 + ${m}))\n"
899}
900
901
902# All major.minor.patch for matching LUAJIT_VERSION_NUM in luajit.h.
903jit2num() {
904 M=0
905 m="${2:-0}"
906 p="${3:-0}"
907
908 IFS=.
909 set -- ${1}
910 unset IFS
911
912 M=${1:-${M}}
913 m=${2:-${m}}
914 p=${3:-${p}}
915
916 checkints $M $m $p
917
918 printf "$((${M} * 10000 + ${m} * 100 + ${p}))\n"
919}
920
921
922mmp2num() {
923 M="${2:-0}"
924 m="${3:-0}"
925 p="${4:-0}"
926
927 IFS=".+-_"
928 set -- ${1}
929 unset IFS
930
931 if isinteger "${1:-}"; then
932 M=${1}
933 fi
934
935 if isinteger "${2:-}"; then
936 m=${2}
937 fi
938
939 if isinteger "${3:-}"; then
940 p=${3}
941 fi
942
943 checkints $M $m $p
944
945 printf "$((${M} * 10000 + ${m} * 100 + ${p}))\n"
946}
947
948
949findlua() {
950 if [ $# -eq 0 ]; then
951 IFS=:
952 set -- ${GLOB:-${GLOB_LUA}}
953 unset IFS
954 fi
955
956 while [ $# -gt 0 ]; do
957 for F in $(findpath "${1}" no "${PATH}"; findpath "${1}" "${RECURSE}" "${BINDIRS}"); do
958 [ -x "$F" ] && safeperm "$F" || continue
959
960 V="$("$F" -e 'print(string.match(_VERSION, [[[%d.]+]]))' </dev/null 2>>/dev/null | head -n1 | sed -ne 's/^\([0123456789][0123456789]*\.[0123456789][0123456789]*\).*/\1/p')"
961 : ${V:=0}
962 V="$((${V%%.*} * 100 + ${V##*.} % 100))"
963
964 [ "${V}" -gt 0 -a "${V}" -ge "${LUA_VER:-0}" ] || continue
965
966 [ "${V}" -gt "${LUA_VER:-0}" -o "${#F}" -lt "${#LUA_PATH}" ] || continue
967
968 [ "${V}" -ge "${API_MIN}" -a "${V}" -le "${API_MAX}" ] || continue
969
970 if [ -n "${JIT_REQ}" ]; then
971 J="$("$F" -v </dev/null 2>&1 | head -n1 | sed -ne 's/^LuaJIT \([0123456789][0123456789]*\.[0123456789][0123456789]*\.[0123456789][0123456789]*\).*/\1/p')"
972 J="$(jit2num ${J:-0})"
973
974 if [ "${JIT_REQ}" = "skip" ]; then
975 [ "${J}" -eq 0 ] || continue
976 elif [ "${JIT_REQ}" = "yes" ]; then
977 [ "${J}" -gt 0 ] || continue
978 [ "${J}" -ge "${JIT_MIN}" ] || continue
979 [ "${J}" -le "${JIT_MAX}" ] || continue
980 fi
981 fi
982
983 LUA_PATH="$F"
984 LUA_VER="$V"
985
986 [ "${SHORTEST}" = "yes" -o "${LUA_VER}" -lt "${API_MAX}" ] || break 2
987 done
988
989 shift
990 done
991
992 if [ -n "${LUA_PATH}" -a -n "${LUA_VER}" ]; then
993 return 0
994 else
995 return 1
996 fi
997}
998
999
1000ccname() {
1001 "${CC}" -E - <<-EOF | awk '/sunpro/||/clang/||/gcc/||/other/{ print $1; exit; }'
1002 #if defined __SUNPRO_C
1003 sunpro
1004 #elif defined __clang__
1005 clang
1006 #elif defined __GNUC__
1007 gcc
1008 #else
1009 other
1010 #endif
1011 EOF
1012}
1013
1014
1015usage() {
1016 cat <<-EOF
1017 usage: ${0##*/} [-I:L:P:d:De:krm:xsv:j:JVh] cppflags|version|lua|luac|...
1018 -I PATH additional search directory for includes
1019 -L PATH additional search directory for libraries
1020 -P PATH additional search directory for binaries
1021 -d PATH use PATH as sandbox directory; a random 16 byte suffix is
1022 generated from /dev/urandom and the directory removed on exit
1023 unless a trailing "/" is present
1024 (default sandbox is \$TMPDIR/${0##*/}-XXXXXXXXXXXXXXXX)
1025 -D do not create a sandbox
1026 -e GLOB glob pattern for finding utilities (lua, luac, etc)
1027 -k query pkg-config if available
1028 -r recursively search directories
1029 -m MAXDEPTH limit recursion to MAXDEPTH (only for GNU and BSD find)
1030 -x do not cross device mounts when recursing
1031 -s find shortest pathname, otherwise print first best match
1032 -v VERSION require specific Lua version or range
1033 (e.g. "5.1" or "5.1-5.2")
1034 -j VERSION require specific LuaJIT version or range
1035 (e.g. "2.0.1"; empty ranges like "-" force any LuaJIT version)
1036 -J skip LuaJIT if encountered
1037 -V print this script's version information
1038 -h print this usage message
1039
1040 cppflags print derived additional CPPFLAGS necessary
1041 ldflags print derived additional LDFLAGS necessary (TODO)
1042 version print derived Lua API version
1043 luac print path to luac utility ($(printf "${GLOB_LUA}" | tr ':' ' '))
1044 lua print path to lua interpreter ($(printf "${GLOB_LUAC}" | tr ':' ' '))
1045 package.path print preferred module install path
1046 package.cpath print preferred C module install path
1047 ccname print CC name (e.g. sunpro, clang, gcc)
1048 evalmacro run internal macro evaluator for debugging
1049 testsym run internal library symbol reader for debugging
1050
1051 This utility is used to derive compiler flags and filesystem paths
1052 necessary to utilize Lua, LuaJIT, and particular versions thereof.
1053 On success it prints the requested information and exits with 0,
1054 otherwise it fails with an exit status of 1.
1055
1056 Note that cppflags may not print anything if no additional flags are
1057 required to compile against the requested API version.
1058
1059 When searching, the highest Lua version is preferred. Searching
1060 stops once the highest version in the allowable range is found
1061 unless the -s flag is specified.
1062
1063 LuaJIT is treated like any other Lua installation. If an explicit
1064 LuaJIT version or range is specified, then only LuaJIT installations
1065 will match. To exclude LuaJIT entirely use the -J switch.
1066
1067 This utility processes the environment variables CC, CPPFLAGS,
1068 LDFLAGS, and PATH if present. If recursion is requested, then
1069 directories specified in CPPFLAGS, LDFLAGS, and PATH are also
1070 recursed.
1071
1072 If the environment variable CPPFLAGS is empty and no -I options are
1073 specified directly, then /usr/include and /usr/local/include are
1074 used when probing for cppflags and API version.
1075
1076 Report bugs to <william@25thandClement.com>
1077 EOF
1078}
1079
1080
1081version() {
1082 cat <<-EOF
1083 luapath $MYVERSION
1084 vendor $MYVENDOR
1085 release $MYVERSION
1086 EOF
1087}
1088
1089
1090while getopts I:L:P:d:De:krm:xsv:j:JVh OPT; do
1091 case "${OPT}" in
1092 I)
1093 INCDIRS="${INCDIRS:-}${INCDIRS:+:}${OPTARG}"
1094 ;;
1095 L)
1096 LIBDIRS="${LIBDIRS:-}${LIBDIRS:+:}${OPTARG}"
1097 ;;
1098 P)
1099 BINDIRS="${BINDIRS:-}${BINDIRS:+:}${OPTARG}"
1100 ;;
1101 d)
1102 SANDBOX="${OPTARG}"
1103 ;;
1104 D)
1105 SANDBOX=
1106 ;;
1107 e)
1108 GLOB="${GLOB:-}${GLOB:+:}${OPTARG}"
1109 ;;
1110 k)
1111 PKGCONFIG="$(command -v pkg-config || true)"
1112 ;;
1113 r)
1114 RECURSE=yes
1115 ;;
1116 m)
1117 if [ -n "${OPTARG##[0123456789]}" ]; then
1118 printf -- "${0##*/}: ${OPTARG}: invalid maxdepth\n" >&2
1119 exit 1
1120 fi
1121
1122 if find "${TMPDIR:-/tmp}" -maxdepth ${OPTARG} -prune >>/dev/null 2>&1; then
1123 MAXDEPTH="-maxdepth ${OPTARG}"
1124 else
1125 printf -- "${0##*/}: $(command -v find): -maxdepth unsupported\n" >&2
1126 fi
1127
1128 ;;
1129 x)
1130 XDEV="-xdev"
1131 ;;
1132 s)
1133 SHORTEST=yes
1134 ;;
1135 v)
1136 MIN=${OPTARG%%[,:-]*}
1137 MAX=${OPTARG##*[,:-]}
1138
1139 API_MIN="$(lua2num ${MIN:-0} 0)"
1140 API_MAX="$(lua2num ${MAX:-99} 99)"
1141
1142 if [ "${API_MIN}" -gt "${API_MAX}" ]; then
1143 printf -- "${0##*/}: ${OPTARG}: invalid version range\n" >&2
1144 exit 1
1145 fi
1146
1147 ;;
1148 j)
1149 MIN=${OPTARG%%[,:-]*}
1150 MAX=${OPTARG##*[,:-]}
1151
1152 JIT_MIN="$(jit2num ${MIN:-0} 0 0)"
1153 JIT_MAX="$(jit2num ${MAX:-99} 99 99)"
1154
1155 if [ "${JIT_MIN}" -gt "${JIT_MAX}" ]; then
1156 printf -- "${0##*/}: ${OPTARG}: invalid version range\n" >&2
1157 exit 1
1158 fi
1159
1160 JIT_REQ=yes
1161 ;;
1162 J)
1163 JIT_REQ=skip
1164 ;;
1165 V)
1166 version
1167 exit 0
1168 ;;
1169 h)
1170 usage
1171 exit 0
1172 ;;
1173 *)
1174 usage >&2
1175 exit 1
1176 ;;
1177 esac
1178done
1179
1180shift $(($OPTIND - 1))
1181
1182
1183for U in "${CC:-cc}" find grep od rm rmdir sed xargs; do
1184 if ! command -v "${U}" >>/dev/null 2>&1; then
1185 printf -- "${0##*/}: ${U}: command not found\n" >&2
1186 fi
1187done
1188
1189
1190if [ -n "${SANDBOX}" ]; then
1191 if [ "${SANDBOX}" = "${SANDBOX%/}" ]; then
1192 if [ ! -c "${DEVRANDOM}" ]; then
1193 # TODO: expand DEVRANDOM into set of different possibilities to check
1194 printf -- "${0##*/}: ${DEVRANDDOM}: no character random device available\n" >&2
1195 exit 1
1196 fi
1197
1198 TMP="${SANDBOX}$(od -An -N8 -tx1 < ${DEVRANDOM} 2>>/dev/null | tr -d ' ')"
1199
1200 if [ ${#TMP} -ne $((${#SANDBOX} + 16)) ]; then
1201 printf -- "${0##*/}: ${SANDBOX}: unable to generate random suffix\n" >&2
1202 exit 1
1203 fi
1204
1205 SANDBOX="${TMP}"
1206
1207 trap "cd .. && rm -f -- ${SANDBOX}/* && rmdir -- ${SANDBOX}" EXIT
1208 fi
1209
1210 if [ ! -d "${SANDBOX}" ]; then
1211 OMASK="$(umask)"
1212 umask 0777
1213 mkdir -m0550 -- "${SANDBOX}" || exit 1
1214 umask ${OMASK}
1215 fi
1216
1217 cd ${SANDBOX}
1218fi
1219
1220
1221CPPDIRS="$(idirs "${CPPFLAGS:-}")"
1222
1223if [ -z "${CPPDIRS}" -a -z "${INCDIRS}" ]; then
1224 INCDIRS="/usr/include:/usr/local/include"
1225fi
1226
1227
1228LDDIRS="$(ldirs "${LDFLAGS:-}")"
1229
1230if [ -z "${LDDIRS}" -a -z "${LIBDIRS}" ]; then
1231 LIBDIRS="/lib:/usr/lib:/usr/local/lib"
1232fi
1233
1234
1235case "${1:-}" in
1236cppflags)
1237 findversion || exit 1
1238
1239 [ "${API_VER:-0}" -gt 0 ] || exit 1
1240
1241 [ -z "${API_DIR:-}" ] || printf -- "-I${API_DIR}\n"
1242
1243 ;;
1244ldflags)
1245 findlib
1246
1247 [ "${LIBLUA_VER:-0}" -gt 0 ] || exit 1
1248
1249 printf -- "-L${LIBLUA_DIR} -l${LIBLUA_LIB}\n"
1250
1251 ;;
1252version)
1253 findversion || exit 1
1254
1255 printf "$(((${API_VER} / 100) % 100)).$((($API_VER) % 100))\n"
1256
1257 ;;
1258libv*)
1259 findlib
1260
1261 [ "${LIBLUA_VER:-0}" -gt 0 ] || exit 1
1262
1263 printf "$(((${LIBLUA_VER} / 100) % 100)).$((($LIBLUA_VER) % 100))\n"
1264
1265 ;;
1266luac)
1267 shift
1268
1269 if [ $# -gt 0 ]; then
1270 append GLOB $*
1271 fi
1272
1273 findluac || exit 1
1274
1275 printf -- "${LUAC_PATH}\n"
1276
1277 ;;
1278lua)
1279 shift
1280
1281 if [ $# -gt 0 ]; then
1282 append GLOB $*
1283 fi
1284
1285 findlua || exit 1
1286
1287 printf -- "${LUA_PATH}\n"
1288
1289 ;;
1290ldir|cdir)
1291 printf -- "${0##*/}: ${1}: deprecated command\n" >&2
1292 MODE="${1}"
1293 shift
1294
1295 if [ $# -gt 0 ]; then
1296 append GLOB $*
1297 fi
1298
1299 findlua || exit 1
1300
1301 if [ "${MODE}" = "cdir" ]; then
1302 findinstalldir package.cpath
1303 else
1304 findinstalldir package.path
1305 fi
1306
1307 ;;
1308package.path|package.cpath)
1309 findlua || exit 1
1310
1311 findinstalldir "$@" || exit 1
1312
1313 ;;
1314ccname)
1315 ccname
1316
1317 ;;
1318evalmacro)
1319 shift
1320
1321 evalmacro $*
1322 ;;
1323testsym)
1324 shift
1325
1326 if testsym $*; then
1327 printf "found\n"
1328 exit 0
1329 else
1330 printf "not found\n"
1331 exit 1
1332 fi
1333 ;;
1334*)
1335 if [ -n "${1:-}" ]; then
1336 printf -- "${0##*/}: ${1}: unknown command\n" >&2
1337 else
1338 printf -- "${0##*/}: no command specified\n" >&2
1339 fi
1340
1341 exit 1
1342 ;;
1343esac
1344
1345exit 0