configure 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #!/bin/sh
  2. # SPDX-FileCopyrightText: 2019-2023 Badwolf Authors <https://hacktivis.me/projects/badwolf>
  3. # SPDX-License-Identifier: BSD-3-Clause
  4. VERSION=1.2.0
  5. VERSION_FULL=${VERSION}$(./version.sh)
  6. DEPS="gtk4 libxml-2.0 webkitgtk-6.0 glib-2.0"
  7. SRCS="bookmarks.c userscripts.c fmt.c fmt_test.c uri.c uri_test.c keybindings.c downloads.c badwolf.c man_uri_scheme.c"
  8. OBJS="bookmarks.o userscripts.o fmt.o uri.o keybindings.o downloads.o badwolf.o man_uri_scheme.o"
  9. OBJS_test="fmt_test.o uri_test.o bookmarks_test.o"
  10. EXE=badwolf
  11. EXE_test="fmt_test uri_test bookmarks_test"
  12. DOCS="usr.bin.badwolf README.md KnowledgeBase.md interface.md"
  13. TRANS="fr pt_BR sr tr de vi"
  14. TRANS_MAN="de fr sr tr vi"
  15. lint_targets=""
  16. min_webkitgtk=2.32.0
  17. min_glib_guri=2.66.0
  18. arg0="$0"
  19. args="$@"
  20. usage() {
  21. cat <<END
  22. Usage: [variables] configure [variables]
  23. Variables:
  24. PREFIX=DIR
  25. BINDIR=DIR
  26. MANDIR=DIR
  27. DOCDIR=DIR
  28. DATADIR=DIR
  29. APPSDIR=DIR
  30. PKGCONFIG=BIN
  31. MSGFMT=BIN
  32. INKSCAPE=BIN
  33. CC=BIN
  34. CFLAGS=OPTIONS
  35. ED=BIN
  36. LDFLAGS=OPTIONS
  37. EXTRA_CFLAGS=OPTIONS
  38. XGETTEXT=BIN
  39. MSGMERGE=BIN
  40. MANDOC=BIN
  41. SHELLCHECK=BIN
  42. FLAWFINDER=BIN
  43. REUSE=BIN
  44. Variables are set in the following order: Default, Environment, Arguments
  45. Dependencies: See README.md
  46. END
  47. }
  48. is_ok() {
  49. status="$?"
  50. if test $status -eq 0; then
  51. printf " OK\n"
  52. else
  53. printf " FAIL\n"
  54. fi
  55. return $status
  56. }
  57. required() {
  58. is_ok || exit 1
  59. }
  60. pkg_config_check() {
  61. printf 'Checking: %s %s ...' "${PKGCONFIG}" "$*"
  62. "${PKGCONFIG}" "$@"
  63. is_ok
  64. }
  65. ## User configuration
  66. # defaults
  67. PREFIX="${PREFIX:-/usr/local}"
  68. PKGCONFIG="${PKGCONFIG:-pkg-config}"
  69. MSGFMT="${MSGFMT:-msgfmt}"
  70. INKSCAPE="${INKSCAPE:-inkscape}"
  71. CC="${CC:-cc}"
  72. CFLAGS="${CFLAGS:--g -O2 -D_FORTIFY_SOURCE=2}"
  73. ED="${ED:-ed}"
  74. XGETTEXT="${XGETTEXT:-xgettext}"
  75. MSGMERGE="${MSGMERGE:-msgmerge}"
  76. MANDOC="${MANDOC:-mandoc}"
  77. SHELLCHECK="${SHELLCHECK:-shellcheck}"
  78. FLAWFINDER="${FLAWFINDER:-flawfinder}"
  79. REUSE="${REUSE:-reuse}"
  80. # Also allow variables through arguments
  81. for i; do
  82. case "$i" in
  83. -h|--help)
  84. usage
  85. exit 1
  86. ;;
  87. -*)
  88. printf "Unknown argument ‘%s’\n" "${i}"
  89. usage
  90. exit 1
  91. ;;
  92. *=*)
  93. # shellcheck disable=SC2163
  94. export "$i"
  95. shift
  96. ;;
  97. *)
  98. printf "Unknown argument ‘%s’\n" "${i}"
  99. usage
  100. exit 1
  101. ;;
  102. esac
  103. done
  104. # Fallback definitions for dirs, based on $PREFIX
  105. BINDIR="${BINDIR:-${PREFIX}/bin}"
  106. MANDIR="${MANDIR:-${PREFIX}/share/man}"
  107. DOCDIR="${DOCDIR:-${PREFIX}/share/doc/badwolf-${VERSION}}"
  108. DATADIR="${DATADIR:-${PREFIX}/share/badwolf}"
  109. APPSDIR="${APPSDIR:-${PREFIX}/share/applications}"
  110. # Add some extra CFLAGS
  111. CFLAGS="${CFLAGS} -Wall -Wextra -Wconversion -Wsign-conversion -Werror=implicit-function-declaration -Werror=implicit-int -Werror=vla ${EXTRA_CFLAGS}"
  112. ## System checks
  113. # commands
  114. printf 'Checking %s command existence ...' "${PKGCONFIG}"
  115. command -v "${PKGCONFIG}" >/dev/null ; required
  116. printf 'Checking %s command existence ...' "${CC}"
  117. command -v "${CC}" >/dev/null ; required
  118. printf 'Checking %s command existence ...' "${ED}"
  119. if command -v "${ED}" >/dev/null ; is_ok
  120. then
  121. :
  122. else
  123. echo 'Warning: Updating of *.pot translation files disabled, you may want to install ed(1)'
  124. ED="false"
  125. fi
  126. printf 'Checking %s command existence ...' "${MANDOC}"
  127. if command -v "${MANDOC}" >/dev/null ; is_ok
  128. then
  129. lint_targets="${lint_targets} lint_mandoc"
  130. else
  131. echo 'Warning: manpage linting via mandoc(1) disabled'
  132. MANDOC="true"
  133. fi
  134. printf 'Checking %s command existence ...' "${XGETTEXT}"
  135. if command -v "${XGETTEXT}" >/dev/null ; is_ok
  136. then
  137. :
  138. else
  139. echo 'Warning: translation updates disabled'
  140. XGETTEXT="true"
  141. fi
  142. printf 'Checking %s command existence ...' "${MSGMERGE}"
  143. if command -v "${MSGMERGE}" >/dev/null ; is_ok
  144. then
  145. :
  146. else
  147. echo 'Warning: translation updates disabled'
  148. MSGMERGE="true"
  149. fi
  150. printf 'Checking %s command existence ...' "${SHELLCHECK}"
  151. if command -v "${SHELLCHECK}" >/dev/null ; is_ok
  152. then
  153. lint_targets="${lint_targets} lint_shellcheck"
  154. else
  155. echo 'Warning: shell linting via shellcheck(1) disabled'
  156. SHELLCHECK="true"
  157. fi
  158. printf 'Checking %s command existence ...' "${FLAWFINDER}"
  159. if command -v "${FLAWFINDER}" >/dev/null ; is_ok
  160. then
  161. lint_targets="${lint_targets} lint_flawfinder"
  162. else
  163. echo 'Warning: C analysis via flawfinder(1) disabled'
  164. FLAWFINDER="true"
  165. fi
  166. printf 'Checking %s command existence ...' "${REUSE}"
  167. if command -v "${REUSE}" >/dev/null ; is_ok
  168. then
  169. lint_targets="${lint_targets} lint_reuse"
  170. else
  171. echo 'Warning: License linting via reuse(1) disabled'
  172. REUSE="true"
  173. fi
  174. echo
  175. # pkg-config
  176. for dep in ${DEPS}
  177. do
  178. pkg_config_check --exists "$dep" || exit 1
  179. done
  180. printf 'Using pkg-config to get CFLAGS for %s ...' "${DEPS}"
  181. get_cflags() { "${PKGCONFIG}" --cflags "${DEPS}"; }
  182. DEPS_cflags="$(get_cflags)"
  183. required
  184. printf 'Using pkg-config to get LIBS for %s ...' "${DEPS}"
  185. get_libs() { "${PKGCONFIG}" --libs "${DEPS}"; }
  186. DEPS_libs="$(get_libs)"
  187. required
  188. echo
  189. printf 'Writing to configure.h ...'
  190. cat >configure.h <<EOF
  191. #define DATADIR "${DATADIR}"
  192. #define PACKAGE "Badwolf"
  193. #define _XOPEN_SOURCE 700
  194. #define _POSIX_C_SOURCE 200809L
  195. #define VERSION "${VERSION_FULL}"
  196. EOF
  197. is_ok
  198. ## Configuration write
  199. printf 'Writing to config.ninja ...'
  200. cat >config.ninja <<EOF
  201. # Autogenerated by $arg0 $args
  202. rule gen_config
  203. command = $arg0 "$args"
  204. generator = 1
  205. build config.ninja: gen_config configure
  206. PREFIX = ${PREFIX}
  207. PKGCONFIG = ${PKGCONFIG}
  208. MSGFMT = ${MSGFMT}
  209. INKSCAPE = ${INKSCAPE}
  210. CC = ${CC}
  211. CFLAGS = ${CFLAGS}
  212. LDFLAGS = ${LDFLAGS}
  213. ED = ${ED}
  214. MANDOC = ${MANDOC}
  215. XGETTEXT = ${XGETTEXT}
  216. MSGMERGE = ${MSGMERGE}
  217. SHELLCHECK = ${SHELLCHECK}
  218. FLAWFINDER = ${FLAWFINDER}
  219. REUSE = ${REUSE}
  220. DEPS_cflags = ${DEPS_cflags}
  221. DEPS_libs = ${DEPS_libs}
  222. 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"
  223. rule xgettext
  224. 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
  225. rule msgmerge
  226. # touch: msgmerge doesn't always updates timestamps
  227. command = \$MSGMERGE --update --backup=off \$out \$in && touch \$out
  228. rule xgettext_man
  229. command = if test -e \$out; $
  230. then po4a-updatepo --format man -M utf-8 --master \$in \$GETTEXT_OPTS --po \$out && \$ED -s \$out <po/pot_license.ed;$
  231. else po4a-gettextize --format man -M utf-8 --master \$in \$GETTEXT_OPTS --po \$out && \$ED -s \$out <po/pot_license.ed;$
  232. fi
  233. rule cc_exe
  234. command = \$CC -std=c11 \$CFLAGS -include configure.h \$DEPS_cflags -o \$out \$in \$LDFLAGS \$DEPS_libs
  235. rule cc_obj
  236. command = \$CC -std=c11 \$CFLAGS -include configure.h \$DEPS_cflags -c -o \$out \$in
  237. build badwolf: cc_exe ${OBJS}
  238. EOF
  239. all="badwolf"
  240. for obj in ${OBJS}; do
  241. obj_c="$(echo "$obj" | sed -e 's;\.o;.c;g')"
  242. echo -n "build ${obj}: cc_obj ${obj_c} | "
  243. grep '#include "' "${obj_c}" | sed -e 's;#include ";;' -e 's;";;' | tr '\n' ' '
  244. echo
  245. done >>config.ninja
  246. if [ "$ED" != "false" ]; then
  247. echo "build po/messages.pot: xgettext ${SRCS} | po/pot_license.ed"
  248. echo 'build po/manpage.pot: xgettext_man badwolf.1 | po/pot_license.ed'
  249. fi >>config.ninja
  250. for trans in ${TRANS}; do
  251. echo "build po/${trans}.po: msgmerge po/messages.pot"
  252. echo "build locale/${trans}/LC_MESSAGES/Badwolf.mo: po2mo po/${trans}.po"
  253. all="${all} locale/${trans}/LC_MESSAGES/Badwolf.mo"
  254. done >>config.ninja
  255. for man in ${TRANS_MAN}; do
  256. echo "build po/${man}_man.po: xgettext_man badwolf.1"
  257. echo "build badwolf.${man}.1: translate_manpage po/${man}_man.po"
  258. bundled="${bundled} badwolf.${man}.1"
  259. trans_man="${trans_man} badwolf.${man}.1"
  260. done >>config.ninja
  261. for i in 24 32 48 64 128 256; do
  262. echo "build icons/hicolor/${i}x${i}/apps/badwolf.png: gen_icon icons/hicolor/scalable/apps/badwolf.svg
  263. width = $i
  264. height = $i"
  265. bundled="${bundled} icons/hicolor/${i}x${i}"
  266. icons_list="${icons_list} icons/hicolor/${i}x${i}/apps/badwolf.png"
  267. done >>config.ninja
  268. cat >>config.ninja <<EOF
  269. build icons: phony | ${icons_list}
  270. build trans_man: phony | ${trans_man}
  271. build bundled: phony | icons trans_man
  272. default ${all}
  273. rule remove
  274. command = rm -fr \${in} \${foo}
  275. build install: install | ${all}
  276. build clean: remove
  277. foo = ${all} ${OBJS} ${OBJS_test}
  278. build distclean: remove | clean
  279. foo = config.ninja configure.h install.sh
  280. build fullclean: remove | distclean
  281. foo = ${bundled}
  282. EOF
  283. is_ok
  284. printf 'Writing to ./install.sh ...'
  285. cat >install.sh <<EOF
  286. # Autogenerated by $arg0 $args
  287. # doins <DIR> <filename ...>
  288. doins() {
  289. dir="\${DESTDIR}/\$1"; shift
  290. mkdir -p "\${dir}/" || exit 1
  291. echo "\$@ → \${dir}/"
  292. cp -pr "\$@" "\${dir}/"
  293. }
  294. # newins <DIR> <orig-filename> <dest-filename>
  295. newins() {
  296. dir="\${DESTDIR}/\$1"
  297. mkdir -p "\${dir}/" || exit 1
  298. echo "\$2 → \${dir}/\$3"
  299. cp -pr "\$2" "\${dir}/\$3"
  300. }
  301. doins "${BINDIR}" ./badwolf
  302. doins "${MANDIR}/man1" ./badwolf.1
  303. for man in ${TRANS_MAN}; do
  304. newins "${MANDIR}/\${man}/man1" "./badwolf.\${man}.1" "badwolf.1"
  305. done
  306. doins "${DATADIR}" ./locale
  307. doins "${DATADIR}" ./interface.css
  308. doins "${APPSDIR}" badwolf.desktop
  309. doins "${DOCDIR}" ${DOCS}
  310. doins "${PREFIX}/share" icons
  311. printf "\nNote: An example AppArmor profile has been installed at '${DOCDIR}/usr.bin.badwolf'\n"
  312. EOF
  313. is_ok
  314. echo 'Done, you can now run ninja or samu'