diff --git a/NEWS.adoc b/NEWS.adoc index d208096758..4876dab631 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -82,6 +82,11 @@ https://github.com/networkupstools/nut/milestone/10 building NUT without it. [#2262] * Builds requested with a specific C/C++ language standard revision via `CFLAGS` and `CXXFLAGS` should again be honoured. [PR #2306] + * Allow requesting detailed debug builds (with disabled optimizations for + binaries to best match the source code) for supported compilers using + `configure` script option `--with-debuginfo`. Note that default autoconf + behavior usually embeds moderate optimizations and debug information on + its own. [PR #2310] - nut-usbinfo.pl, nut-scanner and libnutscan: * Library API version for `libnutscan` was bumped from 2.2.0 to 2.5.0 diff --git a/ci_build.sh b/ci_build.sh index f6491d4373..2e6dc3bd2c 100755 --- a/ci_build.sh +++ b/ci_build.sh @@ -96,6 +96,9 @@ if [ "$BUILD_TYPE" = fightwarn ]; then #[ -n "$NUT_USB_VARIANTS" ] || NUT_USB_VARIANTS=auto fi +# configure default is "no"; an "auto" value is "yes unless CFLAGS say something" +[ -n "${BUILD_DEBUGINFO-}" ] || BUILD_DEBUGINFO="" + # Set this to enable verbose profiling [ -n "${CI_TIME-}" ] || CI_TIME="" case "$CI_TIME" in @@ -1299,6 +1302,10 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp # and errors are found more easily in a wall of text: CONFIG_OPTS+=("--enable-Wcolor") + if [ -n "${BUILD_DEBUGINFO-}" ]; then + CONFIG_OPTS+=("--with-debuginfo=${BUILD_DEBUGINFO}") + fi + # Note: modern auto(re)conf requires pkg-config to generate the configure # script, so to stage the situation of building without one (as if on an # older system) we have to remove it when we already have the script. @@ -1317,6 +1324,15 @@ default|default-alldrv|default-alldrv:no-distcheck|default-all-errors|default-sp fi fi + # When itertating configure.ac or m4 sources, we can end up with an + # existing but useless scropt file - nuke it and restart from scratch! + if [ -s "${CI_BUILDDIR}"/configure ] ; then + if ! sh -n "${CI_BUILDDIR}"/configure 2>/dev/null ; then + echo "=== Starting initial clean-up (from old build products): TAKING SHORTCUT because current configure script syntax is broken" + rm -f "${CI_BUILDDIR}"/Makefile "${CI_BUILDDIR}"/configure + fi + fi + if [ -s Makefile ]; then # Let initial clean-up be at default verbosity @@ -1893,7 +1909,7 @@ bindings) pushd "./bindings/${BINDING}" && ./ci_build.sh ;; ""|inplace) - echo "ERROR: No BUILD_TYPE was specified, doing a minimal default ritual without any required options" >&2 + echo "WARNING: No BUILD_TYPE was specified, doing a minimal default ritual without any *required* build products and with developer-oriented options" >&2 if [ -n "${BUILD_WARNOPT}${BUILD_WARNFATAL}" ]; then echo "WARNING: BUILD_WARNOPT and BUILD_WARNFATAL settings are ignored in this mode (warnings are always enabled and fatal for these developer-oriented builds)" >&2 sleep 5 @@ -1925,6 +1941,15 @@ bindings) fi fi + # When itertating configure.ac or m4 sources, we can end up with an + # existing but useless scropt file - nuke it and restart from scratch! + if [ -s "${CI_BUILDDIR}"/configure ] ; then + if ! sh -n "${CI_BUILDDIR}"/configure 2>/dev/null ; then + echo "=== Starting initial clean-up (from old build products): TAKING SHORTCUT because current configure script syntax is broken" + rm -f "${CI_BUILDDIR}"/Makefile "${CI_BUILDDIR}"/configure + fi + fi + if [ -s Makefile ]; then # Help developers debug: # Let initial clean-up be at default verbosity @@ -1958,6 +1983,12 @@ bindings) CONFIG_OPTS+=("--disable-silent-rules") fi + if [ -n "${BUILD_DEBUGINFO-}" ]; then + CONFIG_OPTS+=("--with-debuginfo=${BUILD_DEBUGINFO}") + else + CONFIG_OPTS+=("--with-debuginfo=auto") + fi + ${CONFIGURE_SCRIPT} "${CONFIG_OPTS[@]}" # NOTE: Currently parallel builds are expected to succeed (as far diff --git a/configure.ac b/configure.ac index 83b5b2a0be..45f4ebcb88 100644 --- a/configure.ac +++ b/configure.ac @@ -103,6 +103,18 @@ If this happens, please retry with GNU C/C++ language mode options instead. ])] ) +dnl +------------------------------------------------------------------- +dnl Help avoid "polluting" CFLAGS etc. with auto-settings like "-g -O2" +dnl at least if we intend to tune --with-debuginfo anyway (where we check +dnl if the caller asked for specific optimizations). Following some +dnl experimentation, we do not want to actually mangle the flags provided +dnl by autoconf - for GCC at least, the rightmost mentions of conflicting +dnl flags on command line win. We just want to know when it is okay to add +dnl ours. They may be inherited from "in-place" build setup though. +test -n "${CONFIG_CFLAGS-}" || CONFIG_CFLAGS="${CFLAGS-}" +test -n "${CONFIG_CXXFLAGS-}" || CONFIG_CXXFLAGS="${CXXFLAGS-}" +dnl +------------------------------------------------------------------- + dnl Default to `configure --enable-silent-rules` or `make V=1` for details? dnl This feature seems to require automake-1.13 or newer (1.11+ by other info) dnl On very old systems can comment it away with little loss (then automake-1.10 @@ -110,21 +122,49 @@ dnl is known to suffice): m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], [AC_MSG_NOTICE([Silent Rules feature not defined in this automake version, skipped])]) +dnl +------------------------------------------------------------------- dnl we need Autoconf 2.61 or better to enable features of Posix that are extensions to C dnl (and actually 2.64 or better for m4/ax_check_compile_flag.m4 when it is sourced) dnl UPDATE: As tested on CentOS 6, its "autoconf-2.63-5.1.el6.noarch" also suffices. dnl But OpenBSD 6.5 requires autoconf-2.65 and automake-1.13 or newer... +dnl AC_MSG_NOTICE([CFLAGS_BEFORE_ACPROG="${CFLAGS-}"]) +dnl AC_MSG_NOTICE([CXXFLAGS_BEFORE_ACPROG="${CXXFLAGS-}"]) AC_MSG_CHECKING(for autoconf macro to enable system extensions) m4_version_prereq(2.61, [ AC_MSG_RESULT(yes) + dnl Causes calls to ac_prog stuff, so dittoed below if "no" AC_USE_SYSTEM_EXTENSIONS ], [ AC_MSG_RESULT(no) + AC_PROG_CC ]) AC_PREREQ([2.63]) dnl #AC_PREREQ([2.64]) +dnl Macro AC_PROG_CC_C99 is obsolete; use AC_PROG_CC +dnl Note that NUT does not support building with C89 anyway +dnl AC_PROG_CC_C99 +dnl Needed for per-target flags +AM_PROG_CC_C_O +AC_PROG_CPP +AC_PROG_CXX +AC_PROG_CXX_C_O + +CFLAGS_AFTER_ACPROG="${CFLAGS-}" +CXXFLAGS_AFTER_ACPROG="${CXXFLAGS-}" + +dnl AC_MSG_NOTICE([CFLAGS_AFTER_ACPROG="${CFLAGS-}"]) +dnl AC_MSG_NOTICE([CXXFLAGS_AFTER_ACPROG="${CXXFLAGS-}"]) + +dnl # LEGACY DEFAULT FALLBACK which NUT had since 2005 or before: +dnl # if autoconf does not set any options, use default/moderate optimizations +CFLAGS=${CFLAGS-"-O"} +dnl # Not so far a legacy, added for consistency in 2024 :) +CXXFLAGS=${CXXFLAGS-"-O"} + +dnl +------------------------------------------------------------------- + dnl Use "./configure --enable-maintainer-mode" to keep Makefile.in and Makefile dnl in sync after Git updates. AM_MAINTAINER_MODE @@ -171,8 +211,6 @@ dnl Fix this early so we can expand with eval later test "${prefix}" = "NONE" && prefix="${ac_default_prefix}" test "${exec_prefix}" = "NONE" && exec_prefix='${prefix}' -CFLAGS=${CFLAGS-"-O"} - dnl Note: for practical and platform-independent use, see AX_REALPATH macro AC_CHECK_PROGS([REALPATH], [realpath], []) @@ -574,11 +612,21 @@ AS_IF([test x"$nut_enable_inplace_runtime" = xyes -a x"${NUT_VERSION_DEPLOYED-}" NUT_VERSION_DEPLOYED="" ]) export NUT_VERSION_DEPLOYED + dnl # Avoid replacement after re-entering: + test -n "${CONFIG_CFLAGS-}" || CONFIG_CFLAGS=" " + test -n "${CONFIG_CXXFLAGS-}" || CONFIG_CXXFLAGS=" " + export CONFIG_CFLAGS + export CONFIG_CXXFLAGS eval exec "$0" $CONFIG_FLAGS_DEPLOYED $CONFIG_FLAGS --disable-inplace-runtime ],[ AC_MSG_NOTICE([No CONFIG_FLAGS were reported or discovered from existing NUT deployment (if any); restarting script for a clean run]) NUT_VERSION_DEPLOYED="" export NUT_VERSION_DEPLOYED + dnl # Avoid replacement after re-entering: + test -n "${CONFIG_CFLAGS-}" || CONFIG_CFLAGS=" " + test -n "${CONFIG_CXXFLAGS-}" || CONFIG_CXXFLAGS=" " + export CONFIG_CFLAGS + export CONFIG_CXXFLAGS AC_MSG_NOTICE([exec "$0" $CONFIG_FLAGS --disable-inplace-runtime]) eval exec "$0" $CONFIG_FLAGS --disable-inplace-runtime ]) @@ -589,15 +637,6 @@ AC_CONFIG_LIBOBJ_DIR([common]) dnl +------------------------------------------------------------------- -dnl AC_PROG_CC -dnl Macro AC_PROG_CC_C99 is obsolete; use AC_PROG_CC -dnl Note that NUT does not support building with C89 anyway -dnl AC_PROG_CC_C99 -dnl Needed for per-target flags -AM_PROG_CC_C_O -AC_PROG_CPP -AC_PROG_CXX -AC_PROG_CXX_C_O AC_PROG_INSTALL AC_PROG_MKDIR_P AC_PROG_LN_S @@ -1609,7 +1648,7 @@ AC_ARG_WITH(all, dnl # if test -z "${with_nut_monitor}"; then with_nut_monitor="${withval}"; fi fi - AC_MSG_RESULT("${withval}") + AC_MSG_RESULT([${withval}]) else AC_MSG_RESULT(not given) fi @@ -1653,6 +1692,9 @@ NUT_ARG_ENABLE([warnings], NUT_ARG_ENABLE([Werror], [fail the build if compiler emits any warnings (treat them as errors)], [no]) +NUT_ARG_WITH([debuginfo], + [enable compiler options for debug-friendly builds of all NUT binaries ("no" by default; "auto" means "yes unless CFLAGS say otherwise")], + [no]) dnl To help find warning/error details in a wall of text, see --enable-Wcolor handled above dnl ---------------------------------------------------------------------- @@ -3573,6 +3615,9 @@ unset CPLUSPLUS_DECL AC_MSG_CHECKING(for have_cppunit) have_cppunit="no" +dnl CPPUNIT_NUT_CXXFLAGS are set below if suitable, but can be +dnl disabled further below if nut_with_debuginfo gets applied +dnl for all NUT build products: CPPUNIT_NUT_CXXFLAGS="" AS_IF([test x"$have_PKG_CONFIG" = xyes], [AS_IF([test x"${have_cxx11}" = xyes], @@ -3656,16 +3701,20 @@ return res ? 0 : 1; dnl # By default keep the originally detected have_cppunit value AC_MSG_CHECKING(for impact from --enable-cppunit option - should we build cppunit tests?) AC_ARG_ENABLE(cppunit, - [AS_HELP_STRING([--enable-cppunit], [enable CPPUNIT tests for C++ bindings])], + [AS_HELP_STRING([--enable-cppunit], [enable CPPUNIT tests for C++ bindings (yes, no, force, auto)])], [AS_CASE(["${enableval}"], - ["yes"], [AS_IF([test x"${have_cppunit}" = xyes], [], [AC_MSG_ERROR([--with-cppunit=yes can not be satisfied])])], + ["force"], [AS_IF([test x"${have_cppunit}" = xyes], [], [ + AC_MSG_WARN([--enable-cppunit=yes can not be satisfied, but developer asked for it]) + have_cppunit=yes + ])], + ["yes"], [AS_IF([test x"${have_cppunit}" = xyes], [], [AC_MSG_ERROR([--enable-cppunit=yes can not be satisfied])])], ["no"], [have_cppunit=no] + dnl # "auto" and other values keep what was detected (or not) )]) AC_MSG_RESULT(${have_cppunit}) NUT_REPORT_FEATURE([build C++ tests with CPPUNIT], [${have_cppunit}], [], [HAVE_CPPUNIT], [Define to enable CPPUNIT tests]) -AC_DEFINE_UNQUOTED(CPPUNIT_NUT_CXXFLAGS, $CPPUNIT_NUT_CXXFLAGS, [Compiler flags for cppunit tests]) AC_MSG_CHECKING(whether to install Augeas configuration-management lenses) AC_ARG_WITH(augeas-lenses-dir, @@ -4286,7 +4335,7 @@ AS_CASE(["${nut_enable_warnings}"], nut_enable_warnings="no" ] ) -AC_MSG_RESULT(["${nut_enable_warnings}"]) +AC_MSG_RESULT([${nut_enable_warnings}]) dnl # Nothing special for gcc - we tend to survive it with GNU standard >= 99 dnl # and fail with strict C standard. Suggestions welcome for "gcc-hard" to @@ -4422,7 +4471,7 @@ AS_CASE(["${nut_enable_Werror}"], CXXFLAGS="${CXXFLAGS} -Wno-error" ] ) -AC_MSG_RESULT(["${nut_enable_Werror}"]) +AC_MSG_RESULT([${nut_enable_Werror}]) dnl Some compilers (e.g. older clang-3.4) have issues with built-in methods dnl that are implemented as macros in system headers -- but only for some @@ -4554,7 +4603,8 @@ AS_IF([test -n "${ac_abs_top_builddir}" && test -d "${ac_abs_top_builddir}"], TOP_BUILDDIR="`cd "$TOP_BUILDDIR" && pwd`" || AC_MSG_ERROR([Can not detect TOP_BUILDDIR])] )] ) -AC_MSG_RESULT(["${TOP_BUILDDIR}"]) +dnl Quoted in case someone copy-pastes this path and it has whitespaces: +AC_MSG_RESULT(['${TOP_BUILDDIR}']) ABS_TOP_BUILDDIR="`cd "${TOP_BUILDDIR}" && pwd`" || AC_MSG_ERROR([Can not detect ABS_TOP_BUILDDIR]) ABS_TOP_SRCDIR="`cd "${abs_srcdir}" && pwd`" || AC_MSG_ERROR([Can not detect ABS_TOP_SRCDIR]) @@ -4658,6 +4708,68 @@ AC_ARG_VAR(CCACHE_PATH) PATH_DURING_CONFIGURE="$PATH" AC_SUBST(PATH_DURING_CONFIGURE) +dnl Some binaries, like CPPUNIT tests, have similar flags already added +dnl We might wipe their specific options below if consistently applying +dnl debug-friendly options to everything +AC_MSG_NOTICE([CONFIG_CFLAGS='${CONFIG_CFLAGS}']) +AC_MSG_NOTICE([CONFIG_CXXFLAGS='${CONFIG_CXXFLAGS}']) +AC_MSG_CHECKING([whether to enable debug info in all NUT binaries]) +nut_with_debuginfo_C="${nut_with_debuginfo}" +nut_with_debuginfo_CXX="${nut_with_debuginfo}" +AS_CASE(["${CONFIG_CFLAGS}"], + [*-O*|*-g*], [ + AS_IF([test x"${nut_with_debuginfo_C}" = xauto], [ + nut_with_debuginfo_C="Related settings already specified by caller CFLAGS, not changing anything" + ]) + ], + [ dnl No competing options are provided + AS_IF([test x"${nut_with_debuginfo_C}" = xauto], [nut_with_debuginfo_C="yes"]) + ]) + +AS_CASE(["${CONFIG_CXXFLAGS}"], + [*-O*|*-g*], [ + AS_IF([test x"${nut_with_debuginfo_CXX}" = xauto], [ + nut_with_debuginfo_CXX="Related settings already specified by caller CXXFLAGS, not changing anything" + ]) + ], + [ dnl No competing options are provided + AS_IF([test x"${nut_with_debuginfo_CXX}" = xauto], [nut_with_debuginfo_CXX="yes"]) + ]) + +AS_CASE(["${nut_with_debuginfo_C}"], + [yes], [ + AS_IF([test x"${CLANGCC}" = x"yes" -o x"${GCC}" = x"yes"], [ + CFLAGS="${CFLAGS} -O0 -g3 -gdwarf-2" + ],[nut_with_debuginfo_C="Unknown C compiler, not adding options"] + )], + dnl # [no]: By default we do not add debug info + [legacy], [ + dnl # Apply legacy defaults if no flags were specified by caller or detected by autoconf + AS_IF([test x"${CFLAGS_AFTER_ACPROG}" = x], [CFLAGS="-O ${CFLAGS}"]) + ] +) + +AS_CASE(["${nut_with_debuginfo_CXX}"], + [yes], [ + AS_IF([test "x$CLANGXX" = xyes -o "x$GXX" = xyes], [ + dnl Where we can enable debug, minimize the optimizations + CXXFLAGS="${CXXFLAGS} -O0 -g3 -gdwarf-2" + dnl Use same settings for CPPUNIT tests (they bump their own by default) + CPPUNIT_NUT_CXXFLAGS="" + ],[nut_with_debuginfo_CXX="Unknown C++ compiler, not adding options"] + )], + dnl # [no]: By default we do not add debug info + [legacy], [ + dnl # Apply legacy defaults if no flags were specified by caller or detected by autoconf + AS_IF([test x"${CXXFLAGS_AFTER_ACPROG}" = x], [CXXFLAGS="-O ${CXXFLAGS}"]) + ] +) + +AC_MSG_RESULT([C: ${nut_with_debuginfo_C}; C++: ${nut_with_debuginfo_CXX}]) + +dnl Only in the end, do you understand... +AC_SUBST(CPPUNIT_NUT_CXXFLAGS) + AC_MSG_NOTICE([Generating "data" files from templates, see below for executable scripts]) AC_CONFIG_FILES([ clients/Makefile diff --git a/docs/nut.dict b/docs/nut.dict index b4b6c3b31a..f0feecc9c9 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3444 utf-8 +personal_ws-1.1 en 3446 utf-8 AAC AAS ABI @@ -1896,6 +1896,7 @@ dataok datasheet datastale dayofweek +dbgsym dblatex dcd dcn @@ -1906,6 +1907,7 @@ deUNV debian debootstrap debouncing +debuginfo deci decrement decrypt diff --git a/m4/nut_report_feature.m4 b/m4/nut_report_feature.m4 index dd2666cd58..02ff814033 100644 --- a/m4/nut_report_feature.m4 +++ b/m4/nut_report_feature.m4 @@ -129,6 +129,23 @@ AC_DEFUN([NUT_REPORT_COMPILERS], echo "NUT Compiler settings:" echo "----------------------" echo "" + if test x"${nut_with_debuginfo_C}" = x"yes" -o x"${nut_with_debuginfo_CXX}" = x"yes" ; then + printf 'NOTE: Settings for ' + if test x"${nut_with_debuginfo_C}" = x"yes" ; then + printf 'C ' + fi + if test x"${nut_with_debuginfo_C}${nut_with_debuginfo_CXX}" = x"yesyes" ; then + printf 'and ' + fi + if test x"${nut_with_debuginfo_CXX}" = x"yes" ; then + printf 'C++ ' + fi + printf 'compiler' + if test x"${nut_with_debuginfo_C}${nut_with_debuginfo_CXX}" = x"yesyes" ; then + printf 's' + fi + printf ' are adjusted for debugging (and minimal optimizations)\n\n' + fi printf '* CC \t: %s\n' "$CC" printf '* CFLAGS \t: %s\n' "$CFLAGS" printf '* CXX \t: %s\n' "$CXX" diff --git a/tests/Makefile.am b/tests/Makefile.am index 8ddb86af43..4d825159a8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -21,6 +21,9 @@ CLEANFILES = *.trs *.log AM_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/drivers AM_CXXFLAGS = -I$(top_srcdir)/include +# Compiler flags for cppunit tests +CPPUNIT_NUT_CXXFLAGS = @CPPUNIT_NUT_CXXFLAGS@ + check_PROGRAMS = $(TESTS) check_SCRIPTS =