Search code examples
cgcctimeglibc

Why does GCC claim clock_gettime() implicitly declared, but the preprocessor is perfectly happy with a related macro?


I'm trying to measure the amount of time an operation is taking, as accurately as possible. My research led me to believe that clock_gettime() and friends is what I want.

However, I can't for the life of me get it to work. Consider this seemingly trivial example:

#include <time.h>
#include <unistd.h>

int main(void)
{
    struct timespec t;
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t);
    return 0;
}

If I run that through the preprocessor, everything looks like it's just fine:

$ cpp time.c | tail -n10
# 1163 "/usr/include/unistd.h" 3 4

# 3 "time.c" 2

int main(void)
{
 struct timespec t;
 clock_gettime(2, &t);
 return 0;
}

However, if I try to compile the preprocessed code, it won't:

$ cpp time.c > time-prep.c
$ cc -o time -Wall -std=c11 -lrt time-prep.c
/tmp/user/1000/cc00SdhB.o: In function `main':
time-prep.c:(.text+0x15): undefined reference to `clock_gettime'
collect2: error: ld returned 1 exit status
$ 

If I try to compile the original, it doesn't go any better:

$ cc -o time -Wall -std=c11 -lrt time.c
time.c: In function ‘main’:
time.c:6:18: error: storage size of ‘t’ isn’t known
time.c:7:2: warning: implicit declaration of function ‘clock_gettime’ [-Wimplicit-function-declaration]
time.c:7:16: error: ‘CLOCK_PROCESS_CPUTIME_ID’ undeclared (first use in this function)
time.c:7:16: note: each undeclared identifier is reported only once for each function it appears in
time.c:6:18: warning: unused variable ‘t’ [-Wunused-variable]
$ 

The man page for clock_gettime says that I need to

Link with -lrt (only for glibc versions before 2.17).

but as you can see, I'm already doing that. Adding or removing -lrt to cc doesn't seem to make any difference whatsoever in my case.

I have looked at /usr/include/time.h but don't see anything obvious that I am missing.

What (presumably trivial) incantation is missing for me to be able to use clock_gettime() in my code?


Solution

  • The Linux documentation for clock_gettime() specifies a feature-test requirement:

    _POSIX_C_SOURCE >= 199309L
    

    You could consider fulfilling that directly, perhaps via a #define directive at the very beginning of your code, since the code in fact does depend on it.

    If you do not provide such a #define, then gcc may nevertheless do it for you, depending on the options you specify to it. By default, it will do. Likewise with -std=gnu99 or -std=gnu11. But you attempted to compile with -std=c11, which asks for strict(ish) compliance with C11. C11 does not define the needed POSIX feature-test macro.