#including <alsa/asoundlib.h> and <sys/time.h> results in multiple definition conflict
Asked Answered
U

2

5

Here is the minimal C program to reproduce:

#include <alsa/asoundlib.h>
#include <sys/time.h>

int main( void )
{
}

This will compile with gcc -c -o timealsa.o timealsa.c, but if you include the -std=c99 switch, you get a redefinition error:

In file included from /usr/include/sys/time.h:28:0,
                 from timealsa.c:3:
/usr/include/bits/time.h:30:8: error: redefinition of ‘struct timeval’
 struct timeval
        ^
In file included from /usr/include/alsa/asoundlib.h:49:0,
                 from timealsa.c:2:
/usr/include/alsa/global.h:138:8: note: originally defined here
 struct timeval {
        ^

How can I resolve this conflict while still using -std=c99?

Uncivil answered 19/9, 2015 at 19:28 Comment(10)
You should use the minimum standard of main which is int main(void){return 0;}Reportage
Yes, you're right (but that's one more line!)Uncivil
@Reportage the return 0 is implicit if not present in C99 (Whcih this question is tagged with). See: https://mcmap.net/q/544503/-why-is-return-0-optional . The void is a problem thoughPettaway
Since the question is focused on the c99 standard I will make it more compliant.Uncivil
@MichaelPetch I found there that Returning 0 from main is in C99 § 5.1.2.2.3Reportage
Indeed reaching the } that terminates the main function returns a value of 0, but we are submarining here into an unrelated issue :)Uncivil
There was about return 0 and not about 0 or something else.Reportage
In C99 it is implicit, so if you don't put return 0 it is implied. This isn't the case for C89/C90 .Pettaway
And it's a bad idea, IMHO, because main() shouldn't be "special". But indeed, this is completely unrelated here. And btw, int main(void) is fine, too.Matteson
@MichaelPetch Sir, sorry now I understood your point :)).Reportage
P
5

Since your question suggests you are using GLIBC's time.h there is a way to avoid this by telling it not to define timeval. Include asoundlib.h first then define _STRUCT_TIMEVAL. The one defined in asoundlib.h will be the one that gets used.

#include <alsa/asoundlib.h>
#ifndef _STRUCT_TIMEVAL
#  define _STRUCT_TIMEVAL
#endif
#include <sys/time.h>

int main( void )
{
}
Pettaway answered 19/9, 2015 at 19:42 Comment(4)
This works - so what does std=c99 bring to the table that makes us then need to explicitly disable sys/time's definition of timeval?Uncivil
@Uncivil it enforces standards compliance, so redefinitions are illegal. Try std=c89, will give you the same result.Matteson
@Uncivil : I have made a small alteration to the code to only define _STRUCT_TIMEVAL if it isn't already defined. There are some warning options like -Wall that may pick up the redefinition of the define as a problem.Pettaway
GCC doesn't come with a time.h. You probably mean glibc. Depending on the target system, GCC can use any of a number of libc implementations.Indole
L
2

With C99 and later you can't have duplicate definitions of the same struct. The problem is that alsa/asoundlib.h includes alsa/global.h which contains this code:

/* for timeval and timespec */
#include <time.h>

...

#ifdef __GLIBC__
#if !defined(_POSIX_C_SOURCE) && !defined(_POSIX_SOURCE)
struct timeval {
        time_t          tv_sec;         /* seconds */
        long            tv_usec;        /* microseconds */
};

struct timespec {
        time_t          tv_sec;         /* seconds */
        long            tv_nsec;        /* nanoseconds */
};
#endif
#endif

So the Michael Petch's solution won't work - by the time you've included alsa/asoundlib.h it is already too late. The proper solution is to define _POSIX_C_SOURCE (_POSIX_SOURCE is obsolete). There's more information about these macros here and here.

For example you could try -D_POSIX_C_SOURCE=200809L. However, if you do that you'll get errors like this:

/usr/include/arm-linux-gnueabihf/sys/time.h:110:20: error: field ‘it_interval’ has incomplete type
     struct timeval it_interval;
                    ^
/usr/include/arm-linux-gnueabihf/sys/time.h:112:20: error: field ‘it_value’ has incomplete type
     struct timeval it_value;
                    ^
/usr/include/arm-linux-gnueabihf/sys/time.h:138:61: error: array type has incomplete element type
 extern int utimes (const char *__file, const struct timeval __tvp[2])
                                                             ^

This is all a big mess of old C code and macro madness. The only way I got it to work was to give up and use -std=gnu11.

Lazaro answered 3/6, 2017 at 17:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.