455 lines
11 KiB
Bash
Executable file
455 lines
11 KiB
Bash
Executable file
#!/bin/sh
|
||
# SPDX-FileCopyrightText: 2019-2023 Badwolf Authors <https://hacktivis.me/projects/badwolf>
|
||
# SPDX-License-Identifier: BSD-3-Clause
|
||
|
||
VERSION=1.3.0
|
||
VERSION_FULL=${VERSION}$(./version.sh)
|
||
DEPS="gtk+-3.0 libxml-2.0"
|
||
|
||
SRCS="bookmarks.c userscripts.c fmt.c fmt_test.c uri.c uri_test.c keybindings.c downloads.c badwolf.c"
|
||
OBJS="bookmarks.o userscripts.o fmt.o uri.o keybindings.o downloads.o badwolf.o"
|
||
OBJS_test="fmt_test.o uri_test.o bookmarks_test.o"
|
||
EXE=badwolf
|
||
EXE_test="fmt_test uri_test bookmarks_test"
|
||
DOCS="usr.bin.badwolf README.md KnowledgeBase.md interface.md"
|
||
|
||
TRANS="fr pt_BR tr de vi"
|
||
TRANS_MAN="de fr tr vi"
|
||
|
||
lint_targets=""
|
||
|
||
min_webkitgtk=2.32.0
|
||
min_glib_guri=2.66.0
|
||
|
||
arg0="$0"
|
||
args="$@"
|
||
|
||
usage() {
|
||
cat <<END
|
||
Usage: [variables] configure [variables]
|
||
|
||
Variables:
|
||
PREFIX=DIR
|
||
BINDIR=DIR
|
||
MANDIR=DIR
|
||
DOCDIR=DIR
|
||
DATADIR=DIR
|
||
APPSDIR=DIR
|
||
|
||
PKGCONFIG=BIN
|
||
MSGFMT=BIN
|
||
INKSCAPE=BIN
|
||
CC=BIN
|
||
CFLAGS=OPTIONS
|
||
ED=BIN
|
||
LDFLAGS=OPTIONS
|
||
EXTRA_CFLAGS=OPTIONS
|
||
XGETTEXT=BIN
|
||
MSGMERGE=BIN
|
||
MANDOC=BIN
|
||
SHELLCHECK=BIN
|
||
FLAWFINDER=BIN
|
||
REUSE=BIN
|
||
|
||
WITH_WEBKITGTK=(4.0|4.1)
|
||
WITH_URI_PARSER=(guri|libsoup2)
|
||
|
||
Variables are set in the following order: Default, Environment, Arguments
|
||
|
||
Dependencies: See README.md
|
||
END
|
||
}
|
||
|
||
is_ok() {
|
||
status="$?"
|
||
|
||
if test $status -eq 0; then
|
||
printf " OK\n"
|
||
else
|
||
printf " FAIL\n"
|
||
fi
|
||
|
||
return $status
|
||
}
|
||
|
||
required() {
|
||
is_ok || exit 1
|
||
}
|
||
|
||
pkg_config_check() {
|
||
printf 'Checking: %s %s ...' "${PKGCONFIG}" "$*"
|
||
"${PKGCONFIG}" "$@"
|
||
is_ok
|
||
}
|
||
|
||
## User configuration
|
||
|
||
# defaults
|
||
PREFIX="${PREFIX:-/usr/local}"
|
||
PKGCONFIG="${PKGCONFIG:-pkg-config}"
|
||
MSGFMT="${MSGFMT:-msgfmt}"
|
||
INKSCAPE="${INKSCAPE:-inkscape}"
|
||
CC="${CC:-cc}"
|
||
CFLAGS="${CFLAGS:--g -O2 -D_FORTIFY_SOURCE=2}"
|
||
ED="${ED:-ed}"
|
||
XGETTEXT="${XGETTEXT:-xgettext}"
|
||
MSGMERGE="${MSGMERGE:-msgmerge}"
|
||
MANDOC="${MANDOC:-mandoc}"
|
||
SHELLCHECK="${SHELLCHECK:-shellcheck}"
|
||
FLAWFINDER="${FLAWFINDER:-flawfinder}"
|
||
REUSE="${REUSE:-reuse}"
|
||
|
||
|
||
# Also allow variables through arguments
|
||
for i; do
|
||
case "$i" in
|
||
-h|--help)
|
||
usage
|
||
exit 1
|
||
;;
|
||
-*)
|
||
printf "Unknown argument ‘%s’\n" "${i}"
|
||
usage
|
||
exit 1
|
||
;;
|
||
*=*)
|
||
# shellcheck disable=SC2163
|
||
export "$i"
|
||
shift
|
||
;;
|
||
*)
|
||
printf "Unknown argument ‘%s’\n" "${i}"
|
||
usage
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# Fallback definitions for dirs, based on $PREFIX
|
||
BINDIR="${BINDIR:-${PREFIX}/bin}"
|
||
MANDIR="${MANDIR:-${PREFIX}/share/man}"
|
||
DOCDIR="${DOCDIR:-${PREFIX}/share/doc/badwolf-${VERSION}}"
|
||
DATADIR="${DATADIR:-${PREFIX}/share/badwolf}"
|
||
APPSDIR="${APPSDIR:-${PREFIX}/share/applications}"
|
||
|
||
# Add some extra CFLAGS
|
||
CFLAGS="${CFLAGS} -Wall -Wextra -Wconversion -Wsign-conversion -Werror=implicit-function-declaration -Werror=implicit-int -Werror=vla ${EXTRA_CFLAGS}"
|
||
|
||
## System checks
|
||
# commands
|
||
printf 'Checking %s command existance ...' "${PKGCONFIG}"
|
||
command -v "${PKGCONFIG}" >/dev/null ; required
|
||
|
||
printf 'Checking %s command existance ...' "${CC}"
|
||
command -v "${CC}" >/dev/null ; required
|
||
|
||
printf 'Checking %s command existance ...' "${ED}"
|
||
if command -v "${ED}" >/dev/null ; is_ok
|
||
then
|
||
:
|
||
else
|
||
echo 'Warning: Fixing copyright in po/*.pot files via ed(1) disabled'
|
||
ED="false"
|
||
fi
|
||
|
||
printf 'Checking %s command existance ...' "${MANDOC}"
|
||
if command -v "${MANDOC}" >/dev/null ; is_ok
|
||
then
|
||
lint_targets="${lint_targets} lint_mandoc"
|
||
else
|
||
echo 'Warning: manpage linting via mandoc(1) disabled'
|
||
MANDOC="true"
|
||
fi
|
||
|
||
printf 'Checking %s command existance ...' "${XGETTEXT}"
|
||
if command -v "${XGETTEXT}" >/dev/null ; is_ok
|
||
then
|
||
if [ "${XGETTEXT}" != "true" ]
|
||
then
|
||
# This is due to NetBSD base system having a very old version of gettext (0.16)
|
||
printf 'Checking if %s --help lists --package-name= option ...' "${XGETTEXT}"
|
||
if "${XGETTEXT}" --help 2>&1 | grep -q package-name=; is_ok
|
||
then
|
||
:
|
||
else
|
||
echo 'Warning: translation updates disabled, you may want to set XGETTEXT'
|
||
XGETTEXT="true"
|
||
fi
|
||
else
|
||
echo 'Warning: translation updates disabled'
|
||
fi
|
||
else
|
||
echo 'Warning: translation updates disabled'
|
||
XGETTEXT="true"
|
||
fi
|
||
|
||
printf 'Checking %s command existance ...' "${MSGMERGE}"
|
||
if command -v "${MSGMERGE}" >/dev/null ; is_ok
|
||
then
|
||
:
|
||
else
|
||
echo 'Warning: translation updates disabled'
|
||
MSGMERGE="true"
|
||
fi
|
||
|
||
printf 'Checking %s command existance ...' "${SHELLCHECK}"
|
||
if command -v "${SHELLCHECK}" >/dev/null ; is_ok
|
||
then
|
||
lint_targets="${lint_targets} lint_shellcheck"
|
||
else
|
||
echo 'Warning: shell linting via shellcheck(1) disabled'
|
||
SHELLCHECK="true"
|
||
fi
|
||
|
||
printf 'Checking %s command existance ...' "${FLAWFINDER}"
|
||
if command -v "${FLAWFINDER}" >/dev/null ; is_ok
|
||
then
|
||
lint_targets="${lint_targets} lint_flawfinder"
|
||
else
|
||
echo 'Warning: C analysis via flawfinder(1) disabled'
|
||
FLAWFINDER="true"
|
||
fi
|
||
|
||
printf 'Checking %s command existance ...' "${REUSE}"
|
||
if command -v "${REUSE}" >/dev/null ; is_ok
|
||
then
|
||
lint_targets="${lint_targets} lint_reuse"
|
||
else
|
||
echo 'Warning: License linting via reuse(1) disabled'
|
||
REUSE="true"
|
||
fi
|
||
|
||
echo
|
||
|
||
# pkg-config
|
||
for dep in ${DEPS}
|
||
do
|
||
pkg_config_check --exists "$dep" || exit 1
|
||
done
|
||
|
||
case "${WITH_WEBKITGTK}n" in
|
||
4.1n)
|
||
pkg_config_check --atleast-version="${min_webkitgtk}" webkit2gtk-4.1 || exit 1
|
||
DEPS="${DEPS} webkit2gtk-4.1"
|
||
;;
|
||
4.0n)
|
||
pkg_config_check --atleast-version="${min_webkitgtk}" webkit2gtk-4.0 || exit 1
|
||
DEPS="${DEPS} webkit2gtk-4.0"
|
||
;;
|
||
n)
|
||
echo "notice: Packagers should consider setting the ABI version (4.0 or 4.1) in WITH_WEBKITGTK" >&2
|
||
if pkg_config_check --atleast-version="${min_webkitgtk}" webkit2gtk-4.1
|
||
then
|
||
DEPS="${DEPS} webkit2gtk-4.1"
|
||
else
|
||
pkg_config_check --atleast-version="${min_webkitgtk}" webkit2gtk-4.0 || exit 1
|
||
DEPS="${DEPS} webkit2gtk-4.0"
|
||
fi
|
||
;;
|
||
*)
|
||
echo "error: invalid webkit2gtk version in WITH_WEBKITGTK environment variable, must be 4.0 or 4.1" >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
|
||
case "${WITH_URI_PARSER}n" in
|
||
gurin)
|
||
echo "URI parser selected: GUri from glib-2.0"
|
||
pkg_config_check --atleast-version="${min_glib_guri}" glib-2.0 || exit 1
|
||
DEPS="${DEPS} glib-2.0"
|
||
;;
|
||
libsoup2n)
|
||
echo "URI parser selected: libsoup-2.4"
|
||
pkg_config_check libsoup-2.4 || exit 1
|
||
DEPS="${DEPS} libsoup-2.4"
|
||
CFLAGS="${CFLAGS} -DUSE_LIBSOUP2"
|
||
|
||
if echo "${DEPS}" | grep -q 'webkit2gtk-4.1'
|
||
then
|
||
echo 'warning: libsoup2 selected while WebKitGTK with libsoup3 API is used' >&2
|
||
fi
|
||
;;
|
||
n)
|
||
echo "notice: Packagers should consider setting the URI parsing library (guri or libsoup2) in WITH_URI_PARSER" >&2
|
||
|
||
if echo "${DEPS}" | grep -q 'webkit2gtk-4.0'
|
||
then
|
||
pkg_config_check libsoup-2.4 || exit 1
|
||
echo "URI parser selected: libsoup-2.4"
|
||
DEPS="${DEPS} libsoup-2.4"
|
||
CFLAGS="${CFLAGS} -DUSE_LIBSOUP2"
|
||
else
|
||
pkg_config_check --atleast-version="${min_glib_guri}" glib-2.0 || exit 1
|
||
echo "URI parser selected: GUri from glib-2.0"
|
||
DEPS="${DEPS} glib-2.0"
|
||
fi
|
||
;;
|
||
*)
|
||
echo "error: invalid uri provider in WITH_URI_PARSER environment variable, must be guri or libsoup2" >&2
|
||
;;
|
||
esac
|
||
|
||
printf 'Using pkg-config to get CFLAGS for %s ...' "${DEPS}"
|
||
get_cflags() { "${PKGCONFIG}" --cflags "${DEPS}"; }
|
||
DEPS_cflags="$(get_cflags)"
|
||
required
|
||
|
||
printf 'Using pkg-config to get LIBS for %s ...' "${DEPS}"
|
||
get_libs() { "${PKGCONFIG}" --libs "${DEPS}"; }
|
||
DEPS_libs="$(get_libs)"
|
||
required
|
||
|
||
echo
|
||
|
||
printf 'Writing to configure.h ...'
|
||
cat >configure.h <<EOF
|
||
#define DATADIR "${DATADIR}"
|
||
#define PACKAGE "Badwolf"
|
||
#define _XOPEN_SOURCE 700
|
||
#define _POSIX_C_SOURCE 200809L
|
||
#define VERSION "${VERSION_FULL}"
|
||
EOF
|
||
is_ok
|
||
|
||
## Configuration write
|
||
printf 'Writing to config.ninja ...'
|
||
cat >config.ninja <<EOF
|
||
# Autogenerated by $arg0 $args
|
||
rule gen_config
|
||
command = $arg0 "$args"
|
||
generator = 1
|
||
|
||
build config.ninja: gen_config configure
|
||
|
||
PREFIX = ${PREFIX}
|
||
PKGCONFIG = ${PKGCONFIG}
|
||
MSGFMT = ${MSGFMT}
|
||
INKSCAPE = ${INKSCAPE}
|
||
CC = ${CC}
|
||
CFLAGS = ${CFLAGS}
|
||
LDFLAGS = ${LDFLAGS}
|
||
ED = ${ED}
|
||
MANDOC = ${MANDOC}
|
||
XGETTEXT = ${XGETTEXT}
|
||
MSGMERGE = ${MSGMERGE}
|
||
SHELLCHECK = ${SHELLCHECK}
|
||
FLAWFINDER = ${FLAWFINDER}
|
||
REUSE = ${REUSE}
|
||
|
||
DEPS_cflags = ${DEPS_cflags}
|
||
DEPS_libs = ${DEPS_libs}
|
||
|
||
GETTEXT_OPTS = --copyright-holder="Badwolf Authors <https://hacktivis.me/projects/badwolf>" --package-name="Badwolf" --package-version="${VERSION_FULL}" --msgid-bugs-address="contact+badwolf-msgid@hacktivis.me"
|
||
|
||
rule xgettext
|
||
command = \$XGETTEXT --keyword=_ --language=C --from-code=UTF-8 -o \$out --add-comments --sort-output --foreign-user --no-location --no-wrap \$GETTEXT_OPTS \$in && ed -s \$out <po/pot_license.ed
|
||
|
||
rule msgmerge
|
||
# touch: msgmerge doesn't always updates timestamps
|
||
command = \$MSGMERGE --update --backup=off \$out \$in && touch \$out
|
||
|
||
rule xgettext_man
|
||
command = if test -e \$out; $
|
||
then po4a-updatepo --format man -M utf-8 --master \$in \$GETTEXT_OPTS --po \$out && ed -s \$out <po/pot_license.ed;$
|
||
else po4a-gettextize --format man -M utf-8 --master \$in \$GETTEXT_OPTS --po \$out && ed -s \$out <po/pot_license.ed;$
|
||
fi
|
||
|
||
rule cc_exe
|
||
command = \$CC -std=c11 \$CFLAGS -include configure.h \$DEPS_cflags -o \$out \$in \$LDFLAGS \$DEPS_libs
|
||
|
||
rule cc_obj
|
||
command = \$CC -std=c11 \$CFLAGS -include configure.h \$DEPS_cflags -c -o \$out \$in
|
||
|
||
build po/messages.pot: xgettext ${SRCS} | po/pot_license.ed
|
||
build badwolf: cc_exe ${OBJS}
|
||
|
||
EOF
|
||
all="badwolf"
|
||
|
||
for obj in ${OBJS}; do
|
||
obj_c="$(echo "$obj" | sed -e 's;\.o;.c;g')"
|
||
echo -n "build ${obj}: cc_obj ${obj_c} | "
|
||
grep '#include "' "${obj_c}" | sed -e 's;#include ";;' -e 's;";;' | tr '\n' ' '
|
||
echo
|
||
done >>config.ninja
|
||
|
||
for trans in ${TRANS}; do
|
||
echo "build po/${trans}.po: msgmerge po/messages.pot"
|
||
echo "build locale/${trans}/LC_MESSAGES/Badwolf.mo: po2mo po/${trans}.po"
|
||
all="${all} locale/${trans}/LC_MESSAGES/Badwolf.mo"
|
||
done >>config.ninja
|
||
|
||
for man in ${TRANS_MAN}; do
|
||
echo "build po/${man}_man.po: xgettext_man badwolf.1"
|
||
echo "build badwolf.${man}.1: translate_manpage po/${man}_man.po"
|
||
bundled="${bundled} badwolf.${man}.1"
|
||
trans_man="${trans_man} badwolf.${man}.1"
|
||
done >>config.ninja
|
||
|
||
for i in 24 32 48 64 128 256; do
|
||
echo "build icons/hicolor/${i}x${i}/apps/badwolf.png: gen_icon icons/hicolor/scalable/apps/badwolf.svg
|
||
width = $i
|
||
height = $i"
|
||
bundled="${bundled} icons/hicolor/${i}x${i}"
|
||
icons_list="${icons_list} icons/hicolor/${i}x${i}/apps/badwolf.png"
|
||
done >>config.ninja
|
||
|
||
cat >>config.ninja <<EOF
|
||
build icons: phony | ${icons_list}
|
||
build trans_man: phony | ${trans_man}
|
||
build bundled: phony | icons trans_man
|
||
|
||
default ${all}
|
||
|
||
rule remove
|
||
command = rm -fr \${in} \${foo}
|
||
|
||
build install: install | ${all}
|
||
build clean: remove
|
||
foo = ${all} ${OBJS} ${OBJS_test}
|
||
build distclean: remove | clean
|
||
foo = config.ninja configure.h install.sh
|
||
build fullclean: remove | distclean
|
||
foo = ${bundled}
|
||
EOF
|
||
|
||
is_ok
|
||
|
||
printf 'Writing to ./install.sh ...'
|
||
cat >install.sh <<EOF
|
||
# Autogenerated by $arg0 $args
|
||
|
||
# doins <DIR> <filename ...>
|
||
doins() {
|
||
dir="\${DESTDIR}/\$1"; shift
|
||
mkdir -p "\${dir}/" || exit 1
|
||
|
||
echo "\$@ → \${dir}/"
|
||
cp -pr "\$@" "\${dir}/"
|
||
}
|
||
# newins <DIR> <orig-filename> <dest-filename>
|
||
newins() {
|
||
dir="\${DESTDIR}/\$1"
|
||
mkdir -p "\${dir}/" || exit 1
|
||
|
||
echo "\$2 → \${dir}/\$3"
|
||
cp -pr "\$2" "\${dir}/\$3"
|
||
}
|
||
|
||
doins "${BINDIR}" ./badwolf
|
||
doins "${MANDIR}/man1" ./badwolf.1
|
||
for man in ${TRANS_MAN}; do
|
||
newins "${MANDIR}/\${man}/man1" "./badwolf.\${man}.1" "badwolf.1"
|
||
done
|
||
doins "${DATADIR}" ./locale
|
||
doins "${DATADIR}" ./interface.css
|
||
doins "${APPSDIR}" badwolf.desktop
|
||
doins "${DOCDIR}" ${DOCS}
|
||
doins "${PREFIX}/share" icons
|
||
|
||
printf "\nNote: An example AppArmor profile has been installed at '${DOCDIR}/usr.bin.badwolf'\n"
|
||
EOF
|
||
|
||
is_ok
|
||
|
||
echo 'Done, you can now run ninja or samu'
|