Search code examples
cpostgresqlgccdebianld

GCC cannot find existing library


I am trying to write a small web application in C, which connects to PostgreSQL using libpq. I installed libpq on Debian 13, and have used the following Makefile to build the source code:

CC = gcc
CFLAGS = -Wall -Wextra -pthread -Ithirdparty -I$(shell pg_config --includedir) -L$(shell pg_config --libdir) -l:$(shell pg_config --libdir)/libpq.so
SRCDIR = server
THIRDPARTY_DIR = thirdparty
SOURCES = $(wildcard $(SRCDIR)/*.c)
THIRDPARTY_SOURCES = $(wildcard $(THIRDPARTY_DIR)/*.c)
OBJS = $(SOURCES:.c=.o) $(THIRDPARTY_SOURCES:.c=.o)
TARGET = onio

$(TARGET): $(OBJS)
    $(CC) $(CFLAGS) -o $(TARGET) $(OBJS)

%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

clean:
    rm -f $(OBJS) $(TARGET)

.PHONY: clean

Take a look at this line:

CFLAGS = -Wall -Wextra -pthread -Ithirdparty -I$(shell pg_config --includedir) -L$(shell pg_config --libdir) -l:$(shell pg_config --libdir)/libpq.so

This Makefile later expands to something like this:

gcc -Wall -Wextra -pthread -Ithirdparty -I/usr/include/postgresql -L/usr/lib/x86_64-linux-gnu -l:/usr/lib/x86_64-linux-gnu/pq.so.5.15 -o onio server/database.o server/dotenv.o server/http.o server/main.o server/request.o thirdparty/cJSON.o thirdparty/cJSON_Utils.o

I get:

/usr/bin/ld: cannot find -l:/usr/lib/x86_64-linux-gnu/libpq.so: No such file or directory
collect2: error: ld returned 1 exit status

I have gone to /usr/lib/x86_64-linux-gnu, and ran ls *libpq*. I've gotten:

libpq.a  libpq.so  libpq.so.5  libpq.so.5.15

Why is GCC not finding these existing libraries? I've tried libpq.a as well, and have tried -lpq before and none of that worked. When I tried -lpq (after the -I and -L), I would get:

database.c:(.text+0x75): undefined reference to `PQconnectdb'
/usr/bin/ld: database.c:(.text+0x8b): undefined reference to `PQstatus'
/usr/bin/ld: database.c:(.text+0x9e): undefined reference to `PQfinish'

Something's clearly wrong, and I can't find out what the error is. Does anybody know what is going on?

I've tried -lpq, -l:/usr/lib/x86_64-linux-gnu/libpq.so, -l:/usr/lib/x86_64-linux-gnu/libpq.a, etc.


Solution

  • Looking at the gcc manpage, you could find the following options:

     -l library
               Search the library named library when linking.  (The second
               alternative with the library as a separate argument is only
               for POSIX compliance and is not recommended.)
    
               The -l option is passed directly to the linker by GCC.  Refer
               to your linker documentation for exact details.  The general
               description below applies to the GNU linker.
    
               The linker searches a standard list of directories for the
               library.  The directories searched include several standard
               system directories plus any that you specify with -L. 
    

    In your example, you already stated the search path of the library with -L and using -l will find the stated library in the linker path you've already placed so you only need to do -lpq

    Also, libpq.so is already in your default search path so in your case, you don't need to set any -L.

    gcc -o myapp myapp.c -lpq
    

    Note: In Unix world, -l<name> will find either lib<name>.a or lib<name>.so in your search path. AFAIK, the default search paths are /lib/ and /usr/lib. (Probably /usr/local/lib on some systems).

    Edit Seeing that you already tried -lpq, you can fix your problem by adding the object files in the gcc command before the linker stuff:

    gcc -o myapp myapp.o file1.o file2.o file3.o -lpq
    

    For more information: https://stackoverflow.com/a/9417294/9432116