nut icon indicating copy to clipboard operation
nut copied to clipboard

Compiling issues with llvm-mingw due to strptime.c

Open Anutrix opened this issue 3 years ago • 8 comments

I tried compiling on WSL2 using llvm-mingw project.

Build failed with following error on make:

...
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I../include -I../include -isystem /usr/local/include -g -O2 -Wno-reserved-identifier -Wno-unknown-warning-option -std=gnu99 -Wno-system-headers -Wall -Wextra -Wsign-compare -pedantic -Wno-error -MT strptime.lo -MD -MP -MF .deps/strptime.Tpo -c strptime.c  -fPIC -DPIC -o .libs/strptime.o
strptime.c:59:25: error: expected ';' before 'uint64_t'
   59 | typedef unsigned __int64 uint64_t;
      |                         ^~~~~~~~~
      |                         ;
strptime.c:59:1: warning: useless type name in empty declaration
   59 | typedef unsigned __int64 uint64_t;
      | ^~~~~~~
strptime.c: In function 'strptime':
strptime.c:389:25: warning: implicit declaration of function '_tzset'; did you mean 'tzset'? [-Wimplicit-function-declaration]
  389 |                         _tzset();
      |                         ^~~~~~
      |                         tzset
At top level:
cc1: note: unrecognized command-line option '-Wno-unknown-warning-option' may have been intended to silence earlier diagnostics
cc1: note: unrecognized command-line option '-Wno-reserved-identifier' may have been intended to silence earlier diagnostics
make[2]: *** [Makefile:603: strptime.lo] Error 1
...

I could make it finish without crashing with following changes:

diff --git a/common/strptime.c b/common/strptime.c
index 1672ded8a..5adb81ebb 100644
--- a/common/strptime.c
+++ b/common/strptime.c
@@ -56,7 +56,7 @@ __weak_alias(strptime,_strptime)
 */
 typedef unsigned char u_char;
 typedef unsigned int uint;
-typedef unsigned __int64 uint64_t;
+// typedef unsigned __int64 uint64_t;
 
 #define	_ctloc(x)		(_CurrentTimeLocale->x)
 
@@ -386,7 +386,7 @@ recurse:
 			continue;
 
 		case 'Z':
-			_tzset();
+			tzset();
 			if (strncasecmp((const char *)bp, gmt, 3) == 0
           || strncasecmp((const char *)bp, utc, 3) == 0) {
 				tm->tm_isdst = 0;

From what I found(brotli, harfbuzz, icu4c, openxr(Khronos Group), vulkan(Khronos Group)), uint64_t needs to be declared only if Visual Studio C++ compiler older than version 1600(Visual Studio 2010) is used, so real fix is:

#if defined(_MSC_VER) && (_MSC_VER < 1600)
    typedef signed   __int8  int8_t;
    typedef unsigned __int8  uint8_t;
    typedef signed   __int16 int16_t;
    typedef unsigned __int16 uint16_t;
    typedef signed   __int32 int32_t;
    typedef unsigned __int32 uint32_t;
    typedef signed   __int64 int64_t;
    typedef unsigned __int64 uint64_t;
#else
    #include <stdint.h>
#endif

I haven't made any PR because I can't test networkupstools/nut well enough. I'm new to it.

I'm not sure about _tzset though. Not fixing it crashed build process with

/usr/bin/ld: ./.libs/libupsclient.so: undefined reference to `_tzset'

Anutrix avatar Sep 04 '22 19:09 Anutrix

Also, dumb question, how to run/use/test it after make is done. Where are binaries built if any?

Anutrix avatar Sep 04 '22 19:09 Anutrix

I believe strptime.c fallback was added from BSD recently to build for existing Windows recipes since mingw also lacks it. So currently it may be able to plug just one leak :)

The "ifdef" for windows versions may make sense in wincompat.h (and make use of it) as well as to (if not yet) tie better into config.h, nut_stdint.h, etc.

On Sun, Sep 4, 2022, 21:52 Numan Zaheer Ahmed @.***> wrote:

Also, dumb question, how to run/use/test it after make is done.

— Reply to this email directly, view it on GitHub https://github.com/networkupstools/nut/issues/1650#issuecomment-1236404524, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAMPTFHUZMRKLXXOZS6TW43V4T4YZANCNFSM6AAAAAAQEOQQJU . You are receiving this because you are subscribed to this thread.Message ID: @.***>

jimklimov avatar Sep 04 '22 21:09 jimklimov

For tests, make check-NIT should do it. Maybe needs --enable-NIT or some such in configure script.

jimklimov avatar Sep 04 '22 21:09 jimklimov

Also, as for "where are the binaries" - usually in same directories as sources if you build in-tree, or dedicated directories in similar tree structure under the build area if you build out-of-tree. With libtool involved, the binaries in the "same dir as source" (e.g. in drivers/) would be LT-wrappers - special EXEs in case of Windows, scripts in POSIX - which set up discovery of DLL/SO libraries you built against. Final binaries would be in .libs/ subdirectory nearby, but would require that you give them DLLs.

You might be better off with e.g. ./ci_build.sh && make DESTDIR="$(pwd)/.inst" install-win-bundle which should try to auto-configure all features it can enable with dependencies it finds on your system and build for them (and generate Makefiles in maintainer mode so editing any Makefile.am gets its resulting Makefile regenerated as part of later make without you manually calling configure script), and create an installation complete with bundled third-party DLLs in the .inst/ subdirectory of the workspace (you can specify another, e.g. /mnt/c/Temp/nut or some such). Then you can just run Windows binaries from there, the OS should prefer to find DLLs in same dirs as EXEs. Finding the DLLs recursively to install them takes time, so if you iterate NUT code/recipes with same environment, later do just make DESTDIR=... install to only install NUT build products over the old files.

jimklimov avatar Sep 05 '22 07:09 jimklimov

Also note, when taming a new toolkit like you do now with llvm-mingw, expect to have more warnings and faults like this. You might have to run ci_build.sh or configure once, and spend a week with repetitive make -s to inch further and further through inconsistencies it finds. To get a broader view of what lies ahead, you can try make -k so it would not abort on first error it sees. Just to gauge if there's a dozen or a thousand warnings to fix.

In the latter case, there will probably be hundreds of instances of same "offense" so when you find once how to address it and replicate that solution, you drastically reduce the amount of errors remaining to fix. For example, you can see many pragmas to hush compiler range-check "faults" around code that does run-time sanity checks for platform-dependently sized integer variables (and/or ints that have a different signedness - and so different maximums - for use in different APIs) roughly like if (val > SIZE_MAX) { fatalx(...) }. First the range-checks appeared to allow responsible casting of sane values; then the pragmas appeared because compilers thought that int-du-jour (or long or short int in another platform) may never exceed INT_MAX :)

Given that Windows part of the codebase so far was built with variants of GCC, and that CLANG's static analysis and similar built-in goodies tends to complain more (and often rightfully), I'd expect this to be a busy adventure.

The NUT configure script options (and ci_buid.sh wrapper) offer a concept of varying "strictness levels" in what it considers the compiler to warn about or turns a blind eye to, as well as whether to require that warnings would be fatal. Current default is "medium" for GCC and CLANG presets, as many warnings were weeded out over an almost two-year effort. With a new toolkit I'd suggest to graduate "minimal" warnings (and outright "apparent" syntax errors like here - probably with some configure scripted detection of current build circumstances and capabilities) first, then the "medium".

The "hard" warnings are not yet solved for the main build scenarios either, see e.g. #1648 for a recent scoop.

jimklimov avatar Sep 05 '22 07:09 jimklimov

If it helps a bit, it was not hard to set up for cross-build from Linux (WSL2) indeed:

:; cd /opt
:; wget https://github.com/mstorsjo/llvm-mingw/releases/download/20220802/llvm-mingw-20220802-msvcrt-ubuntu-18.04-x86_64.tar.xz
:; xzcat llvm-mingw-20220802-msvcrt-ubuntu-18.04-x86_64.tar.xz | tar xf -

:; cd /usr/lib/ccache
:; (cd /opt/llvm-mingw-20220802-msvcrt-ubuntu-18.04-x86_64/bin && ls -1 *mingw*clang*) \
    | while read F ; do ln -s ../../bin/ccache "$F"-11 ; done

Then in NUT workspace (starting in a branch-off from current master) quickly hacked the use of clang for cross-build script:

diff --git a/scripts/Windows/build-mingw-nut.sh b/scripts/Windows/build-mingw-nut.sh
index 30fad9f36..190702e2e 100755
--- a/scripts/Windows/build-mingw-nut.sh
+++ b/scripts/Windows/build-mingw-nut.sh
@@ -87,16 +87,18 @@ if [ "$cmd" == "all64" ] || [ "$cmd" == "b64" ] || [ "$cmd" == "all32" ] || [ "$
        # but this version is very Debian specific!!!
        # FIXME: find something more generic
        BUILD_FLAG="--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE`"
-       export CC="$ARCH-gcc"
-       export CXX="$ARCH-g++"
-       export PATH="/usr/$ARCH/bin:$PATH"
+       export CC="$ARCH-clang"
+       export CXX="$ARCH-clang++"
+       export PATH="/opt/llvm-mingw-20220802-msvcrt-ubuntu-18.04-x86_64/bin:/usr/$ARCH/bin:$PATH"

        # Note: _WIN32_WINNT>=0x0600 is needed for inet_ntop in mingw headers
        # and the value 0xffff is anyway forced into some components at least
        # by netsnmp cflags.
-       export CFLAGS+=" -D_POSIX=1 -D_POSIX_C_SOURCE=200112L -I/usr/$ARCH/include/ -D_WIN32_WINNT=0xffff"
-       export CXXFLAGS+=" -D_POSIX=1 -D_POSIX_C_SOURCE=200112L -I/usr/$ARCH/include/ -D_WIN32_WINNT=0xffff"
-       export LDFLAGS+=" -L/usr/$ARCH/lib/"
+       export CFLAGS+=" -D_POSIX=1 -D_POSIX_C_SOURCE=200112L -I/opt/llvm-mingw-20220802-msvcrt-ubuntu-18.04-x86_64/$ARCH/include/ -D_WIN32_WINNT=0xffff"
+       export CXXFLAGS+=" -D_POSIX=1 -D_POSIX_C_SOURCE=200112L -I/opt/llvm-mingw-20220802-msvcrt-ubuntu-18.04-x86_64/$ARCH/include/ -D_WIN32_WINNT=0xffff"
+       #export CFLAGS+=" -D_POSIX=1 -D_POSIX_C_SOURCE=200112L -I/usr/$ARCH/include/ -D_WIN32_WINNT=0xffff"
+       #export CXXFLAGS+=" -D_POSIX=1 -D_POSIX_C_SOURCE=200112L -I/usr/$ARCH/include/ -D_WIN32_WINNT=0xffff"
+       #export LDFLAGS+=" -L/opt/llvm-mingw-20220802-msvcrt-ubuntu-18.04-x86_64/$ARCH/lib/ -lmingw32 -L/usr/$ARCH/lib/ "
        # Note: installation prefix here is "/" and desired INSTALL_DIR
        # location is passed to `make install` as DESTDIR below.
        $CONFIGURE_SCRIPT $HOST_FLAG $BUILD_FLAG --prefix=/ \

(note that removing LDFLAGS or at least pointer to /usr/$ARCH/lib part seemed crucial towards passing "compiler executable" checks, otherwise it got lost in mingw objects)

And ran with it:

:; BUILD_TYPE=cross-windows-mingw ./ci_build.sh || ( cd scripts/Windows/nut_build && make -k -s)

There are several screenfulls of messages issued by compiler, most of them repetitive (same complaint, different instance).

Some warnings seem reasonable (e.g. argument-less function declarations without (void) explicitly), or #if HAVE_REALPATH sort of feature macros (which autotools only define if they are set, and do not define at all if not) without check for #ifdef (undef implicitly evaluates to 0, but is an error pedantically); others seem like a mismatch between what the configure script's detection assumed about the build environment (e.g. that it needed fallback inline localtime() vs. what the system headers actually serve - having same method, so declarations conflict) which needs some digging in config.log and hammering the test code or flags it tries to reliably work everywhere including the new toolkit. Some leave me puzzled OTOH, like error: 'fprintf' was marked unused but was used [-Werror,-Wused-but-marked-unused]. And quite a few different types of complaints are indeed about strptime.c fallback.

jimklimov avatar Sep 05 '22 08:09 jimklimov

For kicks, finally got around to try "standard-issue" pre-set environment "MSYS2 MinGW Clang x64" in the semi-native build environment; will follow up that thread in #1651 to keep things neatly aligned :)

jimklimov avatar Sep 05 '22 09:09 jimklimov

Quick update: making use of "MSYS2 MinGW Clang x64" was not a low-hanging fruit after all, so abandoning that effort on my side for now, to focus on other things. Discoveries, ideas and other details posted in #1651.

jimklimov avatar Sep 08 '22 08:09 jimklimov