I have several issues to compile a C program to stream sound from Intel Edison to devices (iOS and Android).
I made a C program :
I use alsa/asoundlib.h and pthread.h in my program I don't include sys/time.h because ALSA does not allow this.
I use lot of timeval in my program, when i compile it on my computer i'ts compile fine, but on my edison when I :
gcc -std=c99 -Wall -O0 -ggdb -o sender sender.c spsc_circular_queue.c -lopus -lasound -lpthread
In file included from /usr/include/alsa/asoundlib.h:49:0,
from sender.c:16:
/usr/include/alsa/global.h:145:8: error: redefinition of 'struct timespec'
struct timespec {
^
In file included from /usr/include/alsa/global.h:34:0,
from /usr/include/alsa/asoundlib.h:49,
from sender.c:16:
/usr/include/time.h:120:8: note: originally defined here
struct timespec
^
In file included from /usr/include/time.h:41:0,
from /usr/include/sched.h:34,
from sender.c:18:
/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 sender.c:16:
/usr/include/alsa/global.h:140:8: note: originally defined here
struct timeval {
^
Makefile:16: recipe for target 'sender' failed
make: *** [sender] Error 1
How can I manage to stop these redifinitions ?!
Thank you for your help !
Extra info:
I include :
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <alloca.h>
#include <limits.h>
#include <inttypes.h>
#include <alsa/asoundlib.h>
#include "../opus/include/opus.h"
#include <pthread.h>
#include "spsc_circular_queue.h"
I remove sched.h, nothing happen
ALSA depends on types struct timespec and struct timeval. Its global.h header therefore appropriately does this:
/* for timeval and timespec */
#include <time.h>
However, it seems to be of the opinion that GLIBC defines those structures only when an appropriate feature-test macro has been defined, for that header also says:
#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
It's hard to determine under what circumstances GLIBC actually does declare the wanted structures. It indeed does do so conditionally, but it appears that the conditions, at least in GLIBC v2.17, are more general than ALSA assumes. Thus ALSA seems to have fallen out of sync with GLIBC, if indeed it ever was perfectly synchronized in the first place, and under some conditions it produces the duplicate declaration problem you encountered.
Your best bet is probably to define the _POSIX_C_SOURCE macro when you compile. The values supported by GLIBC are documented on the linked manual page. Any value, except possibly 0, ought to solve the problem for you, but the effects will be broader, so you may need to experiment with different values. To start, I suggest the value 200809L, which is the most inclusive among the values supported by GLIBC:
gcc -D_POSIX_C_SOURCE=200809L -std=c99 -Wall -O0 -ggdb -o sender sender.c spsc_circular_queue.c -lopus -lasound -lpthread
ALSA should then rely on the system's definitions instead of issuing its own, duplicate ones.
Related
I am trying to move some functions to separate file in c project.
I made util.h file with
#ifndef _UTIL_H
#define _UTIL_H
#include <signal.h>
#include <termios.h>
#include <time.h>
...
extern struct timeval tv1, tv2, dtv;
void time_start();
long time_stop();
and I made util.c file with
#include "util.h"
...
struct timeval tv1, tv2, dtv;
void time_start() { gettimeofday(&tv1, &timezone); }
long time_stop()
{
gettimeofday(&tv2, &timezone);
dtv.tv_sec = tv2.tv_sec - tv1.tv_sec;
...
in cmake I have
add_executable(mpptd mpptd.c util.c)
and I get the following errors during compile
[build] ../settings/daemons/util.c: In function ‘time_stop’:
[build] ../settings/daemons/util.c:14:8: error: invalid use of undefined type ‘struct timeval’
[build] dtv.tv_sec = tv2.tv_sec - tv1.tv_sec;
[build] ^
and
[build] ../settings/daemons/util.c: At top level:
[build] ../settings/daemons/util.c:7:16: error: storage size of ‘tv1’ isn’t known
[build] struct timeval tv1, tv2, dtv;
[build] ^~~
What can be wrong here? Why "storage size" error goes later than "undefined type" error? Whouldn't it go earlier?
struct timeval is defined in sys/time.h. You'll need to include that.
#ifndef _UTIL_H
#define _UTIL_H
#include <signal.h>
#include <termios.h>
#include <time.h>
#include <sys/time.h>
...
The struct definition (the part with struct { .. }) must be visible to code using that struct. Simply put that part in a header visible to the code using the struct, then include that header.
Otherwise the struct ends up as a forward declaration, of incomplete type. Incomplete types don't have any size, hence the cryptic errors.
In this case you seem to be using some non-standard, non-POSIX (or possibly obsolete POSIX?) library. Strict compilers (like gcc in -std=c11 -pedantic-errors mode) won't allow non-standard crap in standard headers, so you'll have to include the specific non-standard header separately, the struct won't be found in time.h.
Let's say for instance I want to use the structure timespec, which is defined in time.h. According to the manpages I only need to include time.h. But when compiling in c99, this isn't enough:
#include <stdio.h>
#include <time.h>
struct timespec abcd;
int main(int argc, char *argv[])
{
return 0;
}
According to the info I find online (not in the manpages), I need to add this:
#define _POSIX_C_SOURCE 200809L
So I have a few questions:
How do I know to which value I need _POSIX_C_SOURCE to be equal? I found multiple values online.
Why does the placement of this definition influence the compilation? (cf . infra)
#include <stdio.h>
#define _POSIX_C_SOURCE 200809L
#include <time.h>
struct timespec abcd;
int main(int argc, char *argv[])
{
return 0;
}
$ gcc test.c -Wall -Wpedantic -std=c99 -o test
test.c:9:25: error: field ‘time_last_package’ has incomplete type
struct timespec time_last_package;
compiles well:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <time.h>
....
Thanks
How do I know to which value I need _POSIX_C_SOURCE to be equal? I found multiple values online.
There is one value per POSIX standard definition. So you can use any value which:
defines the functionality you need
is supported by your hosting OS
Best is to use the lowest value that meet both those criteria.
Why does the placement of this definition influence the compilation?
POSIX says :
System Interface Chapter 2. Section 2 The Compilation Environment: A POSIX-conforming application should ensure that the feature test
macro _POSIX_C_SOURCE is defined before inclusion of any header.
Otherwise it may leads to wrong/incompatible included definitions... Defining it before any include ensure that all is under the same POSIX version...
Recommended reading : The Open Group Base Specifications Issue 7, 2018 edition, 2 - General Information
The other answer gives nice background. But, it's also possible to define this at the compiler level so you don't have to put it in your source. With gcc and glibc at least, the command-line option
-D_POSIX_C_SOURCE=199309L
is enough to ensure that nanosleep and struct timespec are available if you include <time.h>.
Please find my code below.
I am getting the error "/usr/include/linux/sysctl.h:40:2: error: unknown type name ‘size_t’"
Searching online, the only suggestion is to make sure you have stddef.h included in your code, which I do as can be seem below. There does not appear to be a solution available outside of this fix, which I have tried, so I am currently at a loss as to how to move forward.
Also note, this code is not pretty, but that is not the main issue with this thread. The error I am getting does not look like it is being thrown from a mistake in my code, but I may be wrong.
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <sys/types.h>
#include <linux/module.h>
#include <stddef.h>
struct nf_hook_ops{
struct list_head *list;
nf_hookfn *hook;
struct module *owner;
u_int8_t pf;
unsigned int hooknum;
int priority; /* Hooks are ordered in ascending priority. */
};
int nf_register_hook(struct nf_hook_ops *reg);
void nf_unregister_hook(struct nf_hook_ops *reg);
struct nf_hook_ops nfho = {
nfho.hook = hook_func_in,
nfho.hooknum = NF_INET_LOCAL_IN,
nfho.pf = PF_INE,
nfho.priority = NF_IP_PRI_FIRST
};
nf_register_hook(&nfho); // Register the hook
C is parsed strictly top to bottom, and #include does plain old textual inclusion, not anything clever that would qualify for the name of "module import". Therefore, the order of #include directives can matter. In this case, you're getting complaints about a type defined by stddef.h, so you must make sure that stddef.h is included before whatever needs it, which could be (indeed, is) another header file.
I can reproduce the error you're getting with the following two-line source file:
#include <linux/sysctl.h>
#include <stddef.h>
→
$ gcc -fsyntax-only test.c
In file included from test.c:1:0:
/usr/include/linux/sysctl.h:39:2: error: unknown type name ‘size_t’
If I exchange the order of the #include lines,
#include <stddef.h>
#include <linux/sysctl.h>
then there is no error. This is a bug in linux/sysctl.h, but I would not hold my breath for it to be fixed. I recommend moving stddef.h to the very top of the include list.
I can not reproduce the problem with your actual list of includes,
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <sys/types.h>
#include <linux/module.h>
#include <stddef.h>
but a gcc -H dump does not show linux/sysctl.h getting pulled in transitively by that set of includes, so probably it's just that I have a different version of the kernel headers on my Linux box than you do.
I am trying to make a C program that uses named pipes to communicate with a C++ program on a Raspberry Pi 3.
The warning that GCC is spitting out when I compile some code of mine:
/home/pi/BluetoothTest/btooth.c|76|warning: implicit declaration of function ‘mknod’ [-Wimplicit-function-declaration]|
Here is the code from for the function, including the #if above it:
#if defined __USE_MISC || defined __USE_BSD || defined __USE_XOPEN_EXTENDED
extern int mknod (const char *__path, __mode_t __mode, __dev_t __dev)
__THROW __nonnull ((1));
and here are the includes that I have in the file:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/rfcomm.h>
//#include <linux/stat.h>
The program attempts to create the pipe here:
umask(0);
fifo = mknod(PIPE_LOC, S_IFIFO|0666, 0);
fp = fopen(PIPE_LOC, "w");
fifo is an int that isn't used anywhere else and fp is a FILE* to the pipe. Some debugging that I have done shows that fifo has a value of -1 after mknod runs, likely because of the compiler not seeming to be able to find the implementation of the function.
How do I make it so that GCC knows where to find the implementation of mknod?
As you can see that for declaration of mknod() function to stay after preprocessing stage, one of three macros (__USE_MISC, __USE_BSD, __USE_XOPEN_EXTENDED) should be defined. Otherwise, declaration of mknod() will be removed during preprocessing stage.
#if defined __USE_MISC || defined __USE_BSD || defined __USE_XOPEN_EXTENDED
extern int mknod (const char *__path, __mode_t __mode, __dev_t __dev)
__THROW __nonnull ((1));
You can use compiler options: -std=gnu99 -D_GNU_SOURCE or you can define these macros on your own and place them above header file inclusion.
I think you're missing a definition of some feature test macro required for the respective headers to define mknod. According to the Linux Programmer's Manual for the function (man 2 mknod) the macros for glibc are:
mknod():
_XOPEN_SOURCE >= 500
|| /* Since glibc 2.19: */ _DEFAULT_SOURCE
|| /* Glibc versions <= 2.19: */ _BSD_SOURCE || _SVID_SOURCE
Try adding -D_XOPEN_SOURCE=500 to your compile flags to see if that helps.
I have three files, say A.c , B.c and C.c, all of which #include common.h
In common.h, I include "sys/socket.h" and I protect the common.h by macros:
#ifndef __COMMON_H
#define __COMMON_H
// body of file goes here
#endif
When i compile the code, I get several errors such as below
In file included from /usr/include/sys/socket.h:40,
from tcpperf.h:4,
from wrapunix.c:1:
/usr/include/bits/socket.h:425: error: conflicting types for 'recvmmsg'
/usr/include/bits/socket.h:425: note: previous declaration of 'recvmmsg' was here
In file included from /usr/include/sys/socket.h:40,
from tcpperf.h:4,
from wrapsock.c:1:
As you can see wrapunix.c and wrapsock.c, they both include tcpperf.h, but tcpperf.h is guarded with macros,yet gcc complains that recvmsg was declared multiple times. How do I resolve this issue?
Update:
Here is the header of tcpperf.h, that is causing issues
#ifndef _TCPPERF_H
#define _TCPPERF_H
#include <sys/types.h>
#include <sys/socket.h>
#include <time.h>
#include <regex.h>
#include <errno.h>
#include <sched.h>
#include <pthread.h>
#include <argp.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <linux/tcp.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <sys/wait.h>
#endif
The above error can be reproduced by providing "-combine -fwhole-program" flags to gcc such as
gcc -std=gnu99 -Wall -combine -fwhole-program -I. error.c wrapunix.c wrapsock.c file1.c file2.c -o file2 -lrt
The error is "conflicting types for 'recvmmsg'" rather than just duplicate definition (which would be tolerated if equal). That means your .c source receives two different version of recvmmsg: one by your direct tcpperf.h inclusion and another one by inclusion it via sys/socket.h. I believe you have another version of tcpperf.h elsewhere in inclusion path with different (perhaps older version) recvmmsg.
The problem is almost certainly related to -combine. This is a bit of a guess, but in looking at the definition of recvmmsg:
extern int recvmmsg (int __fd, struct mmsghdr *__vmessages,
unsigned int __vlen, int __flags,
__const struct timespec *__tmo);
note that it takes a struct mmsghdr as an argument. However, while this prototype is unconditional, struct mmsghdr is only defined if __USE_GNU is set:
#ifdef __USE_GNU
/* For `recvmmsg'. */
struct mmsghdr
{
struct msghdr msg_hdr; /* Actual message header. */
unsigned int msg_len; /* Number of received bytes for the entry. */
};
#endif
-combine is basically equivalent to concatenating all your files together and then compiling them. Is there any chance that between the text of wrapunix.c and wrapsock.c that GNU_SOURCE is being defined? If that happened, then the first definition of recvmmsg would use a definition of struct mmsghdr that was local to just the prototype, while the second definition would use the real struct. Those two definitions would then be incompatible, which would result in the error message that you got.