3

I am trying to compile some code on linux that I KNOW compiles on OSX, but I am getting some issues.

All of the files have headers named .h, and all of the files are in the same directory. I am compiling like this:

gcc *.c -std=c99 -lpthread

And while this code does compile on OSX, I get a bunch of weird linker errors on my Ubuntu install. Am I missing a few compiler options? It is a default Ubuntu-server install with the additional packages gcc and build-essential installed.

In file included from errorLogger.h:24:0,
                 from configParser.h:17,
                 from configParser.c:9:
signalHandling.h:24:18: error: unknown type name ‘sigset_t’
configParser.c: In function ‘parseConfigFile’:
configParser.c:114:5: warning: implicit declaration of function ‘getline’ [-Wimplicit-function-declaration]
In file included from errorLogger.h:24:0,
                 from global.h:18,
                 from connection.h:19,
                 from connection.c:10:
signalHandling.h:24:18: error: unknown type name ‘sigset_t’
connection.c: In function ‘createConnectionQueue’:
connection.c:189:28: warning: assignment makes integer from pointer without a cast [enabled by default]
In file included from errorLogger.h:24:0,
                 from database.h:16,
                 from database.c:9:
signalHandling.h:24:18: error: unknown type name ‘sigset_t’
In file included from errorLogger.h:24:0,
                 from errorLogger.c:10:
signalHandling.h:24:18: error: unknown type name ‘sigset_t’
errorLogger.c: In function ‘reportError’:
errorLogger.c:63:5: warning: implicit declaration of function ‘strerror_r’ [-Wimplicit-function-declaration]
errorLogger.c: In function ‘logMessage’:
errorLogger.c:87:5: warning: implicit declaration of function ‘localtime_r’ [-Wimplicit-function-declaration]
errorLogger.c: In function ‘processErrorQueue’:
errorLogger.c:131:17: warning: implicit declaration of function ‘open’ [-Wimplicit-function-declaration]
errorLogger.c:131:57: error: ‘O_APPEND’ undeclared (first use in this function)
errorLogger.c:131:57: note: each undeclared identifier is reported only once for each function it appears in
errorLogger.c:131:68: error: ‘O_CREAT’ undeclared (first use in this function)
errorLogger.c:131:78: error: ‘O_WRONLY’ undeclared (first use in this function)
errorLogger.c:131:88: error: ‘S_IWRITE’ undeclared (first use in this function)
errorLogger.c:131:99: error: ‘S_IREAD’ undeclared (first use in this function)
errorLogger.c:146:13: warning: implicit declaration of function ‘fsync’ [-Wimplicit-function-declaration]
errorLogger.c: In function ‘startErrorLogger’:
errorLogger.c:167:36: error: ‘O_APPEND’ undeclared (first use in this function)
errorLogger.c:167:47: error: ‘O_CREAT’ undeclared (first use in this function)
errorLogger.c:167:57: error: ‘O_WRONLY’ undeclared (first use in this function)
errorLogger.c:167:67: error: ‘S_IWRITE’ undeclared (first use in this function)
errorLogger.c:167:78: error: ‘S_IREAD’ undeclared (first use in this function)
errorLogger.c:214:57: error: ‘O_EXCL’ undeclared (first use in this function)
errorLogger.c:231:27: warning: assignment makes integer from pointer without a cast [enabled by default]
errorLogger.c: In function ‘closeErrorLogger’:
errorLogger.c:246:9: warning: implicit declaration of function ‘pthread_kill’ [-Wimplicit-function-declaration]
In file included from errorLogger.h:24:0,
                 from global.h:18,
                 from global.c:9:
signalHandling.h:24:18: error: unknown type name ‘sigset_t’
In file included from main.c:23:0:
signalHandling.h:24:18: error: unknown type name ‘sigset_t’
main.c: In function ‘main’:
main.c:53:5: warning: implicit declaration of function ‘blockSignals’ [-Wimplicit-function-declaration]
main.c:61:45: error: invalid application of ‘sizeof’ to incomplete type ‘struct addrinfo’ 
main.c:62:29: error: invalid application of ‘sizeof’ to incomplete type ‘struct addrinfo’ 
main.c:64:10: error: dereferencing pointer to incomplete type
main.c:65:10: error: dereferencing pointer to incomplete type
main.c:66:10: error: dereferencing pointer to incomplete type
main.c:66:23: error: ‘AI_PASSIVE’ undeclared (first use in this function)
main.c:66:23: note: each undeclared identifier is reported only once for each function it appears in
main.c:69:5: warning: implicit declaration of function ‘getaddrinfo’ [-Wimplicit-function-declaration]
main.c:73:9: warning: implicit declaration of function ‘gai_strerror’ [-Wimplicit-function-declaration]
main.c:73:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 4 has type ‘int’ [-Wformat]
main.c:73:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 4 has type ‘int’ [-Wformat]
main.c:81:41: error: dereferencing pointer to incomplete type
main.c:83:30: error: dereferencing pointer to incomplete type
main.c:83:46: error: dereferencing pointer to incomplete type
main.c:83:64: error: dereferencing pointer to incomplete type
main.c:96:30: error: dereferencing pointer to incomplete type
main.c:96:44: error: dereferencing pointer to incomplete type
main.c:112:5: warning: implicit declaration of function ‘freeaddrinfo’ [-Wimplicit-function-declaration]
main.c:138:9: error: unknown type name ‘fd_set’
main.c:142:9: warning: implicit declaration of function ‘FD_ZERO’ [-Wimplicit-function-declaration]
main.c:143:9: warning: implicit declaration of function ‘FD_SET’ [-Wimplicit-function-declaration]
main.c:145:9: warning: implicit declaration of function ‘pselect’ [-Wimplicit-function-declaration]
In file included from signalHandling.c:10:0:
signalHandling.h:24:18: error: unknown type name ‘sigset_t’
signalHandling.c:12:18: error: unknown type name ‘sigset_t’
signalHandling.c: In function ‘setHandler’:
signalHandling.c:51:53: error: invalid application of ‘sizeof’ to incomplete type ‘struct sigaction’ 
signalHandling.c:52:36: error: invalid application of ‘sizeof’ to incomplete type ‘struct sigaction’ 
signalHandling.c:54:5: warning: implicit declaration of function ‘sigemptyset’ [-Wimplicit-function-declaration]
signalHandling.c:54:30: error: dereferencing pointer to incomplete type
signalHandling.c:60:9: warning: implicit declaration of function ‘sigaddset’ [-Wimplicit-function-declaration]
signalHandling.c:60:35: error: dereferencing pointer to incomplete type
signalHandling.c:67:17: error: dereferencing pointer to incomplete type
signalHandling.c:72:9: warning: implicit declaration of function ‘sigaction’ [-Wimplicit-function-declaration]
Adrian Cornish
  • 23,227
  • 13
  • 61
  • 77
charliehorse55
  • 1,940
  • 5
  • 24
  • 38

3 Answers3

12

You are probably missing some #includes which are brought in implicitly on OS X, but not on Linux.

Judging from the error messages, you are probably missing includes for at least:

  • <signal.h> (for sigset_t and others)
  • <fcntl.h> (for O_*)
  • <unistd.h> (for a bunch of stuff)
  • <netdb.h> (for various network functions and constants)
  • <stdio.h> (for getline)

You may also need to define some feature macros (e.g, _POSIX_C_SOURCE) to get certain system-dependent functions, including strerror_r and pselect.

  • Not to mention `stdio.h` (for `getline`), and `string.h` (for `strerror_r`). – netcoder Aug 25 '12 at 01:39
  • Okay, it is down to just errors about `S_IWRITE`, I already have `sys/stat.h` included however. – charliehorse55 Aug 25 '12 at 01:45
  • @charliehorse55: Fix your code. All of it. It's not the compiler's fault, it's your code's fault. If you get that many errors with in C99, I don't want to run your code, ever. – netcoder Aug 25 '12 at 01:46
  • @netcoder They aren't errors really. Undefined reference to `strerror_r`? How is that a code issue IF I have already have `#include ` (Which is required to compile on OSX) – charliehorse55 Aug 25 '12 at 01:55
  • @charliehorse55 Welcome to the fun world of writing portable code ;-) – Adrian Cornish Aug 25 '12 at 02:36
5

I'm assuming that the immediate objective is to get the code to compile at all, and that once that's done, you'll go back and revise the source so it works out of the box on both platforms. That means that hacks are acceptable very short-term; they'll be fixed properly as you gain knowledge about what the portability issues are. (If it's any consolation, the first alternative system to the one where the software was originally developed is usually the hardest; after that, it generally gets easier.)

The first thing to try is:

gcc *.c -std=gnu99 -lpthread

This tells system header files to define many more symbols than -std=c99. (There's some dissent on this topic, which is OK. At the least, if you add -pedantic to a -std=c99 compilation, then symbols in standard C headers defined by POSIX are not exposed unless you also request POSIX support — see below. Since you don't have -pedantic, that may not be a factor in the compilations, in which case quietly move on to the next recommendation, which is the basis for future portability to POSIX systems.)

If that is insufficient to get you back on track, then you'll probably need to use something like:

gcc *.c -std=gnu99 -D_XOPEN_SOURCE=700 -lpthread

This says "Provide me with the POSIX and X/Open functions corresponding to POSIX 2008". You can try 600 and 500 for older versions, but you probably won't need to do so on Linux. In due course, you're likely to set _XOPEN_SOURCE automatically, either through a configuration header or via a configuration tool. While you're getting things to compile at all, specifying it on the command line is OK. In due course, you'll be using a makefile or equivalent to control the compilation and not typing a gcc command line at the shell.)

The sigset_t is defined in <signal.h> under POSIX. So, requesting POSIX support explicitly should get things to compile again properly. If you still get types such as sigset_t undeclared, then there must be a header on Mac OS X that includes the standard headers such as <signal.h> but which does some unrelated task on Linux (and therefore does not include <signal.h>). That will require source code scrutiny. However, it is relatively unlikely to be necessary.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • The only difference between `-std=c99` and `-std=gnu99` is whether the compiler will accept certain GCC language extensions. It does not affect the contents of header files. –  Aug 25 '12 at 01:34
  • It's nice to know about ``, but solving a portability problem by adding `-std=gnu99`? I'm not so happy... – Norman Ramsey Aug 25 '12 at 01:44
  • @NormanRamsey: there's a short-term 'get it compiled' and 'any hack will do' operation, which is what I'm addressing. Then there's the engineered solution which makes the hackery unnecessary, because the code works correctly on both systems automatically or almost automatically (whether because of `autoconf` or conservative assumptions or ...). Any option such as `-std=c99` is inherently specific to GCC; it doesn't apply to other compilers in general. – Jonathan Leffler Aug 25 '12 at 01:47
  • In case of desparation, use (1) `gcc` with the `-H` option (as well as any others you're using) to list where the headers are installed, and (2) `cd /usr/include; grep -r -e sigset_t -l .` (assuming that most of the headers are in `/usr/include`). This will tell you whether `sigset_t` is defined somewhere on your Linux box. If not, you need some extra package installed. If it is, then you have to work out how to get it defined. You can repeat the `grep` exercise for any other missing symbol. – Jonathan Leffler Aug 25 '12 at 02:07
  • That grep command returns a few files, including signal.h when run in /usr/include/. Running gcc with -H shows that that is where it is including signal.h from. – charliehorse55 Aug 25 '12 at 02:15
  • @JonathanLeffler yes it's that short-term mindset that gives me the collywobbles :) – Norman Ramsey Aug 25 '12 at 22:47
  • I got compilation errors on signal related system calls when compiling with `-std=c99`. `-D_XOPEN_SOURCE=700` solved it. – tommyo Apr 25 '13 at 00:00
2

You need to include additional header files because different system headers include other different system headers.

Also for example gcc has been working hard to not included headers that it should not.

Is signalHandling.h including #include <signal.h> where sigset_t is defined?

EDIT

After talking with the OP it seems the problems was a compile/link problem. Compiling the source into object files first and then linking them after seemed to have solved their problem.

Adrian Cornish
  • 23,227
  • 13
  • 61
  • 77
  • signalHandling.h does include `signal.h` – charliehorse55 Aug 25 '12 at 02:15
  • 1
    Have you looked in signal.h `grep -w sigset_t * signal.h:50:typedef __sigset_t sigset_t;` – Adrian Cornish Aug 25 '12 at 02:20
  • Yes, that line is present in `signal.h` – charliehorse55 Aug 25 '12 at 02:23
  • 1
    Is it there if you try compiling `configParser.c` with -E passed to gcc - you may need to pipe the output somewhere and look for it. – Adrian Cornish Aug 25 '12 at 02:27
  • Good idea, I think I may be close to the root of the problem. If I just compile one of my files, I get the error (among others): `connection.c:(.text+0x18a): undefined reference to 'sem_wait'`. However running -E on gcc and then passing it to `grep sem_wait` shows this: `extern int sem_wait (sem_t *__sem); sem_wait(parallelThreads);` – charliehorse55 Aug 25 '12 at 02:39
  • It may also trying to compile each file into a binary (ie link it) you really should add -c to create and object file and then link all the object files into a executable at the end. The error you show is a linker error not a compiler error – Adrian Cornish Aug 25 '12 at 02:40
  • 1
    By the way - passing -E to gcc makes it just preprocess the files - it does not compile them. This can help debugging if there are macro expansion issues/#define issues. Basically this is showing the code gcc will try and compile for you – Adrian Cornish Aug 25 '12 at 02:43
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/15791/discussion-between-charliehorse55-and-adrian-cornish) – charliehorse55 Aug 25 '12 at 02:48