diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba0b5bff..c19cce40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,6 +91,25 @@ jobs: - name: Distcheck run: make distcheck DISTCHECK_CONFIGURE_FLAGS='--enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --enable-hwloc --enable-setuid --enable-delayacct --enable-sensors --enable-capabilities' + build-ubuntu-latest-gcc-static: + runs-on: ubuntu-latest + # Enable LTO, might trigger additional warnings on advanced inlining + env: + CFLAGS: -O3 -g -flto + LDFLAGS: -O3 -g -flto + steps: + - uses: actions/checkout@v2 + - name: Install Dependencies + run: sudo apt-get install libncursesw5-dev libtinfo-dev libgpm-dev libsensors4-dev libcap-dev + - name: Bootstrap + run: ./autogen.sh + - name: Configure + run: ./configure --enable-static --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --disable-hwloc --enable-setuid --disable-delayacct --enable-sensors --enable-capabilities + - name: Build + run: make -k + - name: Distcheck + run: make distcheck DISTCHECK_CONFIGURE_FLAGS='--enable-static --enable-werror --enable-openvz --enable-vserver --enable-ancient-vserver --enable-unicode --disable-hwloc --enable-setuid --disable-delayacct --enable-sensors --enable-capabilities' + build-ubuntu-latest-clang-analyzer: runs-on: ubuntu-latest env: diff --git a/README b/README index 47d40b13..609c2795 100644 --- a/README +++ b/README @@ -61,6 +61,9 @@ By default `make install` will install into `/usr/local`, for changing the path * `--enable-setuid`: enable setuid support for privilege dropping default: *no* + *`--enable-static`: + build a static htop binary; hwloc and delay accounting are not supported + default: *no* * `--enable-debug`: Enable asserts and internal sanity checks; implies a performance penalty default: *no* diff --git a/configure.ac b/configure.ac index d873cba7..9df9e060 100644 --- a/configure.ac +++ b/configure.ac @@ -71,6 +71,31 @@ AS_IF([test "x$ac_cv_prog_cc_c99" = xno], [AC_MSG_ERROR([htop is written in C99. # ---------------------------------------------------------------------- +# ---------------------------------------------------------------------- +# Checks for static build. +# ---------------------------------------------------------------------- + +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static], + [build a static htop binary @<:@default=no@:>@])], + [], + [enable_static=no]) +case "$enable_static" in + no) + ;; + yes) + AC_DEFINE([BUILD_STATIC], [1], [Define if building static binary.]) + CFLAGS="$CFLAGS -static" + LDFLAGS="$LDFLAGS -static" + ;; + *) + AC_MSG_ERROR([bad value '$enable_static' for --enable-static option]) + ;; +esac + +# ---------------------------------------------------------------------- + + # ---------------------------------------------------------------------- # Checks for generic header files. # ---------------------------------------------------------------------- @@ -137,7 +162,9 @@ if test "$my_htop_platform" = freebsd; then fi if test "$my_htop_platform" = linux; then - AC_SEARCH_LIBS([dlopen], [dl dld], [], [AC_MSG_ERROR([can not find required function dlopen()])]) + if test "$enable_static" != yes; then + AC_SEARCH_LIBS([dlopen], [dl dld], [], [AC_MSG_ERROR([can not find required function dlopen()])]) + fi fi if test "$my_htop_platform" = openbsd; then @@ -170,6 +197,10 @@ if test "$my_htop_platform" = darwin; then AC_CHECK_FUNCS([mach_timebase_info]) fi +if test "$my_htop_platform" = linux && test "x$enable_static" = xyes; then + AC_CHECK_LIB([systemd], [sd_bus_open_system]) +fi + # ---------------------------------------------------------------------- @@ -189,10 +220,8 @@ m4_define([HTOP_CHECK_SCRIPT], htop_config_script_cflags=$([$4] --cflags 2> /dev/null) fi htop_script_success=no - htop_save_LDFLAGS="$LDFLAGS" htop_save_CFLAGS="$CFLAGS" if test ! "x$htop_config_script_libs" = x; then - LDFLAGS="$htop_config_script_libs $LDFLAGS" CFLAGS="$htop_config_script_cflags $CFLAGS" AC_CHECK_LIB([$1], [$2], [ AC_DEFINE([$3], 1, [The library is present.]) @@ -200,8 +229,9 @@ m4_define([HTOP_CHECK_SCRIPT], htop_script_success=yes ], [ CFLAGS="$htop_save_CFLAGS" + ], [ + $htop_config_script_libs ]) - LDFLAGS="$htop_save_LDFLAGS" fi if test "x$htop_script_success" = xno; then [$5] @@ -212,7 +242,7 @@ m4_define([HTOP_CHECK_SCRIPT], m4_define([HTOP_CHECK_LIB], [ AC_CHECK_LIB([$1], [$2], [ - AC_DEFINE([$3], 1, [The library is present.]) + AC_DEFINE([$3], [1], [The library is present.]) LIBS="-l[$1] $LIBS " ], [$4]) ]) @@ -223,13 +253,13 @@ AC_ARG_ENABLE([unicode], [], [enable_unicode=yes]) if test "x$enable_unicode" = xyes; then - HTOP_CHECK_SCRIPT([ncursesw6], [addnwstr], [HAVE_LIBNCURSESW], "ncursesw6-config", - HTOP_CHECK_SCRIPT([ncursesw], [addnwstr], [HAVE_LIBNCURSESW], "ncursesw6-config", - HTOP_CHECK_SCRIPT([ncursesw], [addnwstr], [HAVE_LIBNCURSESW], "ncursesw5-config", - HTOP_CHECK_SCRIPT([ncurses], [addnwstr], [HAVE_LIBNCURSESW], "ncurses5-config", - HTOP_CHECK_LIB([ncursesw6], [addnwstr], [HAVE_LIBNCURSESW], - HTOP_CHECK_LIB([ncursesw], [addnwstr], [HAVE_LIBNCURSESW], - HTOP_CHECK_LIB([ncurses], [addnwstr], [HAVE_LIBNCURSESW], + HTOP_CHECK_SCRIPT([ncursesw6], [waddnwstr], [HAVE_LIBNCURSESW], "ncursesw6-config", + HTOP_CHECK_SCRIPT([ncursesw], [waddnwstr], [HAVE_LIBNCURSESW], "ncursesw6-config", + HTOP_CHECK_SCRIPT([ncursesw], [waddnwstr], [HAVE_LIBNCURSESW], "ncursesw5-config", + HTOP_CHECK_SCRIPT([ncurses], [waddnwstr], [HAVE_LIBNCURSESW], "ncurses5-config", + HTOP_CHECK_LIB([ncursesw6], [waddnwstr], [HAVE_LIBNCURSESW], + HTOP_CHECK_LIB([ncursesw], [waddnwstr], [HAVE_LIBNCURSESW], + HTOP_CHECK_LIB([ncurses], [waddnwstr], [HAVE_LIBNCURSESW], AC_MSG_ERROR([can not find required library libncursesw; you may want to use --disable-unicode]) ))))))) @@ -243,10 +273,10 @@ if test "x$enable_unicode" = xyes; then # (at this point we already link against a working ncurses library with wide character support) AC_SEARCH_LIBS([keypad], [tinfow tinfo]) else - HTOP_CHECK_SCRIPT([ncurses6], [refresh], [HAVE_LIBNCURSES], [ncurses6-config], - HTOP_CHECK_SCRIPT([ncurses], [refresh], [HAVE_LIBNCURSES], [ncurses5-config], - HTOP_CHECK_LIB([ncurses6], [refresh], [HAVE_LIBNCURSES], - HTOP_CHECK_LIB([ncurses], [refresh], [HAVE_LIBNCURSES], + HTOP_CHECK_SCRIPT([ncurses6], [wnoutrefresh], [HAVE_LIBNCURSES], [ncurses6-config], + HTOP_CHECK_SCRIPT([ncurses], [wnoutrefresh], [HAVE_LIBNCURSES], [ncurses5-config], + HTOP_CHECK_LIB([ncurses6], [wnoutrefresh], [HAVE_LIBNCURSES], + HTOP_CHECK_LIB([ncurses], [wnoutrefresh], [HAVE_LIBNCURSES], AC_MSG_ERROR([can not find required library libncurses]) )))) @@ -260,6 +290,9 @@ else # (at this point we already link against a working ncurses library) AC_SEARCH_LIBS([keypad], [tinfo]) fi +if test "$enable_static" = yes; then + AC_SEARCH_LIBS([Gpm_GetEvent], [gpm]) +fi AC_ARG_ENABLE([hwloc], @@ -405,20 +438,24 @@ case "$enable_delayacct" in no) ;; check) - m4_ifdef([PKG_PROG_PKG_CONFIG], [ - enable_delayacct=yes - PKG_PROG_PKG_CONFIG() - PKG_CHECK_MODULES(LIBNL3, libnl-3.0, [], [enable_delayacct=no]) - PKG_CHECK_MODULES(LIBNL3GENL, libnl-genl-3.0, [], [enable_delayacct=no]) - if test "$enable_delayacct" = yes; then - CFLAGS="$CFLAGS $LIBNL3_CFLAGS $LIBNL3GENL_CFLAGS" - LIBS="$LIBS $LIBNL3_LIBS $LIBNL3GENL_LIBS" - AC_DEFINE([HAVE_DELAYACCT], [1], [Define if delay accounting support should be enabled.]) - fi - ], [ + if test "$enable_static" = yes; then enable_delayacct=no - AC_MSG_NOTICE([Linux delay accounting support can not be enabled, cause pkg-config is required for checking its availability]) - ]) + else + m4_ifdef([PKG_PROG_PKG_CONFIG], [ + enable_delayacct=yes + PKG_PROG_PKG_CONFIG() + PKG_CHECK_MODULES(LIBNL3, libnl-3.0, [], [enable_delayacct=no]) + PKG_CHECK_MODULES(LIBNL3GENL, libnl-genl-3.0, [], [enable_delayacct=no]) + if test "$enable_delayacct" = yes; then + CFLAGS="$CFLAGS $LIBNL3_CFLAGS $LIBNL3GENL_CFLAGS" + LIBS="$LIBS $LIBNL3_LIBS $LIBNL3GENL_LIBS" + AC_DEFINE([HAVE_DELAYACCT], [1], [Define if delay accounting support should be enabled.]) + fi + ], [ + enable_delayacct=no + AC_MSG_NOTICE([Linux delay accounting support can not be enabled, cause pkg-config is required for checking its availability]) + ]) + fi ;; yes) m4_ifdef([PKG_PROG_PKG_CONFIG], [ @@ -450,10 +487,16 @@ case "$enable_sensors" in ;; check) enable_sensors=yes + if test "$enable_static" = yes; then + AC_CHECK_LIB([sensors], [sensors_init], [], [enable_sensors=no]) + fi AC_CHECK_HEADERS([sensors/sensors.h], [], [enable_sensors=no]) ;; yes) - AC_CHECK_HEADERS([sensors/sensors.h], [], [AC_MSG_ERROR([can not find required header file ensors/sensors.h])]) + if test "$enable_static" = yes; then + AC_CHECK_LIB([sensors], [sensors_init], [], [AC_MSG_ERROR([can not find required library libsensors])]) + fi + AC_CHECK_HEADERS([sensors/sensors.h], [], [AC_MSG_ERROR([can not find required header file sensors/sensors.h])]) ;; *) AC_MSG_ERROR([bad value '$enable_sensors' for --enable-sensors]) @@ -576,4 +619,5 @@ AC_MSG_RESULT([ hwloc: $enable_hwloc setuid: $enable_setuid debug: $enable_debug + static: $enable_static ]) diff --git a/linux/LibSensors.c b/linux/LibSensors.c index 158829aa..f94bcff7 100644 --- a/linux/LibSensors.c +++ b/linux/LibSensors.c @@ -10,6 +10,19 @@ #include "XUtils.h" +#ifdef BUILD_STATIC + +#define sym_sensors_init sensors_init +#define sym_sensors_cleanup sensors_cleanup +#define sym_sensors_get_detected_chips sensors_get_detected_chips +#define sym_sensors_snprintf_chip_name sensors_snprintf_chip_name +#define sym_sensors_get_features sensors_get_features +#define sym_sensors_get_subfeature sensors_get_subfeature +#define sym_sensors_get_value sensors_get_value +#define sym_sensors_get_label sensors_get_label + +#else + static int (*sym_sensors_init)(FILE*); static void (*sym_sensors_cleanup)(void); static const sensors_chip_name* (*sym_sensors_get_detected_chips)(const sensors_chip_name*, int*); @@ -21,7 +34,15 @@ static char* (*sym_sensors_get_label)(const sensors_chip_name*, const sensors_fe static void* dlopenHandle = NULL; +#endif /* BUILD_STATIC */ + int LibSensors_init(FILE* input) { +#ifdef BUILD_STATIC + + return sym_sensors_init(input); + +#else + if (!dlopenHandle) { /* Find the unversioned libsensors.so (symlink) and prefer that, but Debian has .so.5 and Fedora .so.4 without matching symlinks (unless people install the -dev packages) */ @@ -56,29 +77,42 @@ int LibSensors_init(FILE* input) { return sym_sensors_init(input); + dlfailure: if (dlopenHandle) { dlclose(dlopenHandle); dlopenHandle = NULL; } return -1; + +#endif /* BUILD_STATIC */ } void LibSensors_cleanup(void) { +#ifdef BUILD_STATIC + + sym_sensors_cleanup(); + +#else + if (dlopenHandle) { sym_sensors_cleanup(); dlclose(dlopenHandle); dlopenHandle = NULL; } + +#endif /* BUILD_STATIC */ } void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int cpuCount) { for (unsigned int i = 0; i <= cpuCount; i++) cpus[i].temperature = NAN; +#ifndef BUILD_STATIC if (!dlopenHandle) return; +#endif /* !BUILD_STATIC */ unsigned int coreTempCount = 0; diff --git a/linux/SystemdMeter.c b/linux/SystemdMeter.c index 75c666f8..f6dcb3fb 100644 --- a/linux/SystemdMeter.c +++ b/linux/SystemdMeter.c @@ -21,8 +21,19 @@ in the source distribution for its full text. #include "RichString.h" #include "XUtils.h" +#if defined(BUILD_STATIC) && defined(HAVE_LIBSYSTEMD) +#include +#endif -#define INVALID_VALUE ((unsigned int)-1) + +#ifdef BUILD_STATIC + +#define sym_sd_bus_open_system sd_bus_open_system +#define sym_sd_bus_get_property_string sd_bus_get_property_string +#define sym_sd_bus_get_property_trivial sd_bus_get_property_trivial +#define sym_sd_bus_unref sd_bus_unref + +#else typedef void sd_bus; typedef void sd_bus_error; @@ -30,19 +41,35 @@ static int (*sym_sd_bus_open_system)(sd_bus**); static int (*sym_sd_bus_get_property_string)(sd_bus*, const char*, const char*, const char*, const char*, sd_bus_error*, char**); static int (*sym_sd_bus_get_property_trivial)(sd_bus*, const char*, const char*, const char*, const char*, sd_bus_error*, char, void*); static sd_bus* (*sym_sd_bus_unref)(sd_bus*); +static void* dlopenHandle = NULL; + +#endif /* BUILD_STATIC */ + +#if !defined(BUILD_STATIC) || defined(HAVE_LIBSYSTEMD) +static sd_bus* bus = NULL; +#endif /* !BUILD_STATIC || HAVE_LIBSYSTEMD */ + + +#define INVALID_VALUE ((unsigned int)-1) static char* systemState = NULL; static unsigned int nFailedUnits = INVALID_VALUE; static unsigned int nInstalledJobs = INVALID_VALUE; static unsigned int nNames = INVALID_VALUE; static unsigned int nJobs = INVALID_VALUE; -static void* dlopenHandle = NULL; -static sd_bus* bus = NULL; static void SystemdMeter_done(ATTR_UNUSED Meter* this) { free(systemState); systemState = NULL; +#ifdef BUILD_STATIC +# ifdef HAVE_LIBSYSTEMD + if (bus) { + sym_sd_bus_unref(bus); + } + bus = NULL; +# endif /* HAVE_LIBSYSTEMD */ +#else /* BUILD_STATIC */ if (bus && dlopenHandle) { sym_sd_bus_unref(bus); } @@ -52,9 +79,12 @@ static void SystemdMeter_done(ATTR_UNUSED Meter* this) { dlclose(dlopenHandle); dlopenHandle = NULL; } +#endif /* BUILD_STATIC */ } +#if !defined(BUILD_STATIC) || defined(HAVE_LIBSYSTEMD) static int updateViaLib(void) { +#ifndef BUILD_STATIC if (!dlopenHandle) { dlopenHandle = dlopen("libsystemd.so.0", RTLD_LAZY); if (!dlopenHandle) @@ -76,6 +106,7 @@ static int updateViaLib(void) { #undef resolve } +#endif /* !BUILD_STATIC */ int r; @@ -152,13 +183,16 @@ busfailure: bus = NULL; return -2; +#ifndef BUILD_STATIC dlfailure: if (dlopenHandle) { dlclose(dlopenHandle); dlopenHandle = NULL; } return -1; +#endif /* !BUILD_STATIC */ } +#endif /* !BUILD_STATIC || HAVE_LIBSYSTEMD */ static void updateViaExec(void) { int fdpair[2]; @@ -233,8 +267,12 @@ static void SystemdMeter_updateValues(ATTR_UNUSED Meter* this, char* buffer, siz systemState = NULL; nFailedUnits = nInstalledJobs = nNames = nJobs = INVALID_VALUE; +#if !defined(BUILD_STATIC) || defined(HAVE_LIBSYSTEMD) if (updateViaLib() < 0) updateViaExec(); +#else + updateViaExec(); +#endif /* !BUILD_STATIC || HAVE_LIBSYSTEMD */ xSnprintf(buffer, size, "%s", systemState ? systemState : "???"); }