Build failure for mingw targets with latest Clang 15
Building libshout for mingw targets, with the very latest (unreleased) Clang 15 fails, with this error:
../../../../src/common/timing/timing.c:73:5: error: call to undeclared function 'gettimeofday'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
gettimeofday(&mtv, NULL);
^
1 error generated.
With previous Clang versions, this was a nonfatal warning:
../../../../src/common/timing/timing.c:73:5: warning: implicit declaration of function 'gettimeofday' is invalid in C99 [-Wimplicit-function-declaration]
gettimeofday(&mtv, NULL);
^
1 warning generated.
Clang 15 has changed to make such implicit function declarations a hard error by default, see https://github.com/llvm/llvm-project/commit/7d644e1215b376ec5e915df9ea2eeb56e2d94626 for details.
Key parts of the arguments for it are:
C89 had a questionable feature where the compiler would implicitly declare a function that the user called but was never previously declared. The resulting function would be globally declared as
extern int func();
-- a function without a prototype which accepts zero or more arguments.C99 removed support for this questionable feature due to severe security concerns. However, there was no deprecation period; C89 had the feature, C99 didn't. So Clang (and GCC) both supported the functionality as an extension in C99 and later modes.
[...]
However, because this feature will not be supported in C2x mode, we've diagnosed it as being invalid for so long, the security concerns with the feature, and the trivial workaround for users (declare the function), we now default the extension warning to an error in C99-C17 mode.
While Clang 15 still is unreleased, this policy may still change - but nevertheless, the warning is entirely valid in any case, and should be fixed.
The issue at hand is caused by the following parts in icecast-common's timing/timing.c
:
#ifdef _WIN32
#include <windows.h>
#include <mmsystem.h>
#else
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#include <unistd.h>
#endif
Followed by:
uint64_t timing_get_time(void)
{
#ifdef HAVE_GETTIMEOFDAY
struct timeval mtv;
gettimeofday(&mtv, NULL);
return (uint64_t)(mtv.tv_sec) * 1000 + (uint64_t)(mtv.tv_usec) / 1000;
#elif HAVE_FTIME
struct timeb t;
ftime(&t);
return t.time * 1000 + t.millitm;
#else
#error need time query handler
#endif
}
In the case of a mingw build, HAVE_GETTIMEOFDAY
is defined, so the implementation of timing_get_time
tries using gettimeofday
. But the header inclusion block above only bothers to try to include <sys/time.h>
if specifically running on a platform other than Windows.
Suggested fix:
Decouple the includes of <sys/time.h>
and <time.h>
from the #ifdef _WIN32 ... #else
block. If TIME_WITH_SYS_TIME
is defined, try to include both <sys/time.h>
and <time.h>
. If not, include <time.h>
(which is a standard C header which I presume icecast can assume exists) and/or possibly <sys/time.h>
(based on HAVE_SYS_TIME_H
- which doesn't seem to be set by the configure script in libshout though).
diff --git a/timing/timing.c b/timing/timing.c
index 9be67d5..7efa776 100644
--- a/timing/timing.c
+++ b/timing/timing.c
@@ -35,8 +35,11 @@
#ifdef _WIN32
#include <windows.h>
#include <mmsystem.h>
#else
+#include <unistd.h>
+#endif
+
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
@@ -46,11 +49,8 @@
# include <time.h>
# endif
#endif
-#include <unistd.h>
-#endif
-
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif