kalle konsida
kalle konsida

Reputation: 343

undefined reference to pthread_create and pthread_join

I am trying to build my program but keep getting the same error messages:

undefined reference to pthread_create  
undefined reference to pthread_join

I have included pthread.h and in my makefile im compiling with -pthread.

int threadAmount = strtol(nrthr, NULL, 0);
    threadAmount--;

    if(threadAmount > 0){
        pthread_t tids[threadAmount];

        for(int i = 0;i < threadAmount; i++){
            pthread_attr_t attr;
            pthread_attr_init(&attr);
            pthread_create(&tids[i],&attr,search,&t1);
        }

        for(int i = 0;i < threadAmount; i++){
            pthread_join(tids[i],NULL);
        }
    }

It's where I'm calling create and join where it's complaining. What could be the problem?

The makefile used to build:

CC=gcc
CFLAGS= -pthread -std=gnu11 -Wall -Wextra -Werror -Wmissing-declarations -Wmissing-prototypes -Werror-implicit-function-declaration -Wreturn-type -Wparentheses -Wunused -Wold-style-definition -Wundef -Wshadow -Wstrict-prototypes -Wswitch-default -Wunreachable-code

all: mfind

list.o: list.c list.h
    $(CC) -c list.c $(CFLAGS)

mfind.o: mfind.c list.h
    $(CC) -c mfind.c $(CFLAGS) 

mfind: mfind.o list.o
    $(CC) mfind.o list.o -o mfind

clean:
    rm -f *.o mfind

mfind is the main program and list.c is an implemented list.

Upvotes: 5

Views: 12696

Answers (2)

jww
jww

Reputation: 102376

list.o: list.c list.h
    $(CC) -c list.c $(CFLAGS)

mfind.o: mfind.c list.h
    $(CC) -c mfind.c $(CFLAGS) 

mfind: mfind.o list.o
    $(CC) mfind.o list.o -o mfind

It looks like some of your recipes are missing CFLAGS, which includes the option -pthread. I believe it should be:

list.o: list.c list.h
    $(CC) $(CFLAGS) -c list.c

mfind.o: mfind.c list.h
    $(CC) $(CFLAGS) -c mfind.c

mfind: mfind.o list.o
    $(CC) $(CFLAGS) mfind.o list.o -o mfind

...

Its OK to CFLAGS to the output artifact. In fact, you should use the same CFLAGS (and CXXFLAGS) when the compiler driver drives link. You should also always use the compiler driver because it takes care of turning options, like -pthread, -fopenmp and -fsanitize=undefined, into the proper options and libraries for the linker.

If interested, here are the default rule used with GNUmake: Catalogue of Built-In Rules. Notice the recipe for *.c files includes CFLAGS:

Compiling C programs

n.o is made automatically from n.c with a recipe of the form $(CC) $(CPPFLAGS) $(CFLAGS) -c.

If you use the following from the GNU Make manual, then you should also add -pthread to LDFLAGS. But I recommend you follow what the compiler guys tell us, and that is to drive link through the compiler driver.

Linking a single object file

n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS).

Upvotes: 2

P.P
P.P

Reputation: 121417

-pthread doesn't belong in CFLAGS. As you already found, the libraries that are needed must be at the end of the command line options after all the object files. You need to put -pthread in LDLIBS since you have a makefile.

From https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html:

LDLIBS

Library flags or names given to compilers when they are supposed to invoke the linker, ‘ld’. LOADLIBES is a deprecated (but still supported) alternative to LDLIBS. Non-library linker flags, such as -L, should go in the LDFLAGS variable.

Upvotes: 1

Related Questions