CC.rc was the only "mandatory" detection, which was weird and inconsistent. Instead, make it optional like the others, and have it set a HAVE_CC variable appropriately (and have CXX.rc work the same way). Then, add a default.required.rc.od that checks the HAVE_* for any variable and aborts if it is not available. This allows us to fix confusing behaviour in allconfig.do, which would try every compiler on the system, but redo would print a (non-fatal) error message (and prevent redo-stamp optimization) when CC.rc failed for any non-working compilers. Now CC.rc just politely reports that it didn't find a compiler. Then we change all.rc.od to make CC.rc mandatory. Reported-by: Nathaniel Filardo <nwfilardo@gmail.com>
240 lines
5.1 KiB
Bash
240 lines
5.1 KiB
Bash
# This script starts with $PWD=output dir, $S=input dir.
|
|
REDOCONF="$S/redoconf"
|
|
if [ ! -d "$S" ] || [ ! -f "$REDOCONF/default.do.sh" ]; then
|
|
echo "default.do.sh: \$S is not set correctly." >&2
|
|
exit 99
|
|
fi
|
|
. "$REDOCONF/utils.sh"
|
|
RC_TARGET="$1"
|
|
rm -f "$RC_TARGET.log"
|
|
|
|
redo-ifchange "$REDOCONF/rc.sh" "$REDOCONF/utils.sh"
|
|
|
|
_rc_exit_check() {
|
|
if [ -z "$RC_INCLUDE_RAN" ]; then
|
|
echo "Fatal: used redoconf/rc.sh but didn't call rc_include." >&2
|
|
exit 91
|
|
elif [ -n "$RC_QUEUE" ]; then
|
|
echo "Fatal: must call rc_save or rc_undo before ending." >&2
|
|
exit 92
|
|
fi
|
|
}
|
|
trap _rc_exit_check EXIT
|
|
|
|
rc_hook() {
|
|
# nothing by default; can be overridden
|
|
:
|
|
}
|
|
|
|
# Declare that a variable *named* $1 is used
|
|
# as input for the current script, and provide
|
|
# a help message in $2 for use with
|
|
# configure --help-flags.
|
|
helpmsg() {
|
|
# Nothing to do by default
|
|
rc_hook "$1"
|
|
}
|
|
|
|
# Assign the string $2 to the global variable
|
|
# *named* by $1.
|
|
replaceln() {
|
|
rc_hook "$1"
|
|
eval $1=\$2
|
|
}
|
|
|
|
# If $2 is nonempty, append a newline and $2 to
|
|
# the global variable *named* by $1
|
|
appendln() {
|
|
rc_hook "$1"
|
|
eval local tmp=\"\$$1\$NL\$2\"
|
|
eval $1='${tmp#$NL}'
|
|
}
|
|
|
|
# Write a command line that calls "uses $1",
|
|
# including proper sh-escaping.
|
|
rc_helpmsg() {
|
|
local cmd="helpmsg"
|
|
cmd="helpmsg $1 $(shquote "$2")"
|
|
eval "$cmd"
|
|
appendln RC_HELP_QUEUE "$cmd"
|
|
}
|
|
|
|
_rc_record() {
|
|
if ! contains_line "$RC_CHANGED" "$1"; then
|
|
local oldv=
|
|
eval oldv="\$$1"
|
|
eval "old$1=\$oldv"
|
|
RC_CHANGED="$RC_CHANGED$NL$1"
|
|
fi
|
|
}
|
|
|
|
# Write a command line that calls "appendln $1 $2",
|
|
# including properly sh-escaping $2.
|
|
rc_appendln() {
|
|
RC_LOG="$RC_LOG $1 += $(shquote "$2")$NL"
|
|
_rc_record "$1"
|
|
local cmd="appendln $1 $(shquote "$2")"
|
|
eval "$cmd"
|
|
appendln RC_QUEUE "$cmd"
|
|
}
|
|
|
|
# Write a command line that replaces $1 with $2,
|
|
# including properly sh-escaping $2.
|
|
# This is good for variables like CC and CXX, where
|
|
# appending isn't what we want.
|
|
rc_replaceln() {
|
|
RC_LOG="$RC_LOG $1 = $(shquote "$2")$NL"
|
|
_rc_record "$1"
|
|
local cmd="replaceln $1 $(shquote "$2")"
|
|
eval "$cmd"
|
|
appendln RC_QUEUE "$cmd"
|
|
}
|
|
|
|
# Read compiler variables from _init.rc and the listed .rc files.
|
|
# Runs redo-ifchange to generate the .rc files as needed.
|
|
rc_include() {
|
|
local d="" want="" target="$RC_TARGET" ops4="$PS4"
|
|
RC_INCLUDE_RAN=1
|
|
for d in rc/_init.rc "$@"; do
|
|
if [ "$d" = "${d%.rc}" ]; then
|
|
xecho "$0: rc_include: '$d' must end in .rc" >&2
|
|
exit 99
|
|
fi
|
|
if ! contains_line "$RC_INCLUDES" "$d"; then
|
|
want="$want$NL$d"
|
|
RC_INCLUDES="$RC_INCLUDES$NL$d"
|
|
fi
|
|
done
|
|
want="${want#$NL}"
|
|
if [ -n "$want" ]; then
|
|
xIFS="$IFS"
|
|
IFS="$NL"
|
|
set -f
|
|
redo-ifchange $want
|
|
for d in $want; do
|
|
IFS="$xIFS"
|
|
set +f
|
|
RC_TARGET="$d"
|
|
PS4="$PS4[$d] "
|
|
[ ! -e "$d" ] || { :; . "./$d"; }
|
|
PS4="$ops4"
|
|
done
|
|
IFS="$xIFS"
|
|
set +f
|
|
fi
|
|
unset RC_QUEUE
|
|
PS4="$ops4"
|
|
RC_TARGET="$target"
|
|
}
|
|
|
|
# Undo the currently enqueued rc_appendln and rc_replaceln
|
|
# actions, restoring the affected variables back to their
|
|
# original values.
|
|
rc_undo() {
|
|
local xIFS="$IFS" v=
|
|
IFS="$NL"
|
|
for k in $RC_CHANGED; do
|
|
eval v="\$old$k"
|
|
eval "$k=\$v"
|
|
done
|
|
unset RC_CHANGED
|
|
unset RC_QUEUE
|
|
unset RC_LOG
|
|
}
|
|
|
|
# Write the currently active rc_include,
|
|
# rc_replaceln, and rc_appendln commands to stdout,
|
|
# to produce the final .rc file.
|
|
rc_save() {
|
|
printf '%s' "${RC_LOG}" >&2
|
|
if [ -n "$RC_INCLUDES" ]; then
|
|
(
|
|
xIFS="$IFS"
|
|
IFS="$NL"
|
|
printf 'rc_include '
|
|
for d in $RC_INCLUDES; do
|
|
printf '%s ' "$d"
|
|
done
|
|
printf '\n'
|
|
)
|
|
fi
|
|
xecho "$RC_HELP_QUEUE"
|
|
xecho "$RC_QUEUE"
|
|
unset RC_QUEUE
|
|
unset RC_CHANGED
|
|
}
|
|
|
|
rc_compile() {
|
|
redo-ifchange "$REDOCONF/trycompile"
|
|
( . "$REDOCONF/trycompile" "$@" ) >>"$RC_TARGET.log" 2>&1
|
|
}
|
|
|
|
_pkg_config() {
|
|
(
|
|
IFS="$NL"
|
|
set -f
|
|
$PKG_CONFIG $PKG_CONFIG_FLAGS "$@"
|
|
)
|
|
}
|
|
|
|
_rc_pkg_add() {
|
|
local var="$1" vvar= want=
|
|
shift
|
|
if [ -n "$HAVE_PKG_CONFIG" ]; then
|
|
for d in "$@"; do
|
|
if _pkg_config --exists "$d"; then
|
|
want="$want $d"
|
|
fi
|
|
done
|
|
if [ -n "$want" ]; then
|
|
rc_appendln CPPFLAGS \
|
|
"$(rc_splitwords \
|
|
"$(_pkg_config --cflags $want)")"
|
|
vvar="$(rc_splitwords \
|
|
"$(_pkg_config --libs $want)")"
|
|
rc_appendln "$var" "$vvar"
|
|
fi
|
|
else
|
|
echo "(pkg-config is missing)" >&2
|
|
fi
|
|
}
|
|
|
|
# Determine whether packages listed in $2 all exists and are functional,
|
|
# by finding them using pkg-config and running the command in $3..$n.
|
|
#
|
|
# If the package works:
|
|
# HAVE_$1 is set to 1
|
|
# CPPFLAGS and the variable named by $1 are updated with compiler and
|
|
# linker flags, respectively.
|
|
# else:
|
|
# HAVE_$1 is set to blank.
|
|
#
|
|
# Returns success in either case. Check detection results in the
|
|
# HAVE_$1 variable if needed.
|
|
rc_pkg_detect() {
|
|
if ! contains_line "$RC_INCLUDES" rc/pkg-config.rc; then
|
|
echo "Error: include pkg-config.rc before using rc_pkg_*" >&2
|
|
return 1
|
|
fi
|
|
if [ "$#" -lt 3 ]; then
|
|
echo "Error: rc_pkg_detect needs a command to test." >&2
|
|
return 1
|
|
fi
|
|
local var="$1" vvar="" pkgs="$2"
|
|
shift
|
|
shift
|
|
eval vvar="\$$var"
|
|
rc_helpmsg "$var" "Extra linker options for '$pkgs'"
|
|
if [ -z "$vvar" ]; then
|
|
_rc_pkg_add "$var" $pkgs
|
|
eval vvar="\$$var"
|
|
fi
|
|
appendln LIBS "$vvar"
|
|
if ("$@"); then
|
|
rc_replaceln "HAVE_$var" 1
|
|
else
|
|
rc_undo
|
|
rc_replaceln "HAVE_$var" ""
|
|
rc_replaceln "$var" ""
|
|
fi
|
|
}
|