TL;DR: I'm working on a C exercise that uses dlfcn.h
to open shared libraries. Despite adding (what I think are) the correct flags based on other posts, I'm still getting undefined reference to
errors for dlopen
, dlsym
and a few other functions defined in dlfcn.h
(error message and make-file are included below).
I've obv included the following at the start of my .c
file: #include <dlfcn.h>
What am I doing wrong?
Detailed version:
I'm working on exercise 30 of Learn C The Hard Way
and am puzzled as to what else I need to do in order to get the libex29_tests.c
program (very last section of code on the page) to compile correctly. As you can probably tell, shared libraries/makefiles/compiler flags are new to me at the moment.
What I've tried so far: Based on the following posts, I've tried adding the -ldl
flag by adding LIBS=-ldl fPIC
and/or LDFLAGS+=-ldl
to various parts of my Makefile but am still having issues. The version of the makefile in the book (included below, as reference) does include an -ldl
flag albeit via slightly different syntax. In any case, I continue to get the same error message.
- Linux c++ error: undefined reference to 'dlopen'
- g++ cannot link to libdl even with -ldl flag
- undefined reference to 'dlopen' in installing phonetisaurus
- C++: Undefined symbols when loading shared library with dlopen()
Any suggestions?
These are the errors that I get. These errors assume the version of the makefile
included below. However, as I'd mentioned, changing the syntax for the -ldl
flag results in virtually the same error message(s).
~/.../lchw/ex30_automated$ make
cc -std=gnu99 -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG -fPIC -c -o src/libex29.o src/libex29.c
src/libex29.c: In function ‘fail_on_purpose’:
src/libex29.c:42:33: warning: unused parameter ‘msg’ [-Wunused-parameter]
int fail_on_purpose(const char *msg)
^
ar rcs build/libYOUR_LIBRARY.a src/libex29.o
ranlib build/libYOUR_LIBRARY.a
cc -shared -o build/libYOUR_LIBRARY.so src/libex29.o
cc -std=gnu99 -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG build/libYOUR_LIBRARY.a tests/libex29_tests.c -o tests/libex29_tests
In file included from tests/libex29_tests.c:1:0:
tests/libex29_tests.c: In function ‘main’:
src/minunit.h:14:38: warning: parameter ‘argc’ set but not used [-Wunused-but-set-parameter]
#define RUN_TESTS(name) int main(int argc, char *argv[]) {\
^
tests/libex29_tests.c:64:1: note: in expansion of macro ‘RUN_TESTS’
RUN_TESTS(all_tests);
^
/tmp/dchaudh/ccwzxpC3.o: In function `check_function':
/home/dchaudh/Dropbox/dchaudh/wc/lchw/ex30_automated/tests/libex29_tests.c:10: undefined reference to `dlsym'
/home/dchaudh/Dropbox/dchaudh/wc/lchw/ex30_automated/tests/libex29_tests.c:11: undefined reference to `dlerror'
/tmp/dchaudh/ccwzxpC3.o: In function `test_dlopen':
/home/dchaudh/Dropbox/dchaudh/wc/lchw/ex30_automated/tests/libex29_tests.c:23: undefined reference to `dlopen'
/tmp/dchaudh/ccwzxpC3.o: In function `test_dlclose':
/home/dchaudh/Dropbox/dchaudh/wc/lchw/ex30_automated/tests/libex29_tests.c:46: undefined reference to `dlclose'
collect2: error: ld returned 1 exit status
make: *** [tests/libex29_tests] Error 1
Here's the latest makefile
as per the book. It does include the -ldl
flag, as you can see on the second line.
CFLAGS=-std=gnu99 -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS)
LIBS=-ldl $(OPTLIBS)
PREFIX?=/usr/local
SOURCES=$(wildcard src/**/*.c src/*.c)
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
TARGET=build/libYOUR_LIBRARY.a
SO_TARGET=$(patsubst %.a,%.so,$(TARGET))
# The Target Build
all: $(TARGET) $(SO_TARGET) tests
dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
dev: all
$(TARGET): CFLAGS += -fPIC
$(TARGET): build $(OBJECTS)
ar rcs $@ $(OBJECTS)
ranlib $@
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared -o $@ $(OBJECTS)
build:
@mkdir -p build
@mkdir -p bin
# The Unit Tests
.PHONY: tests
tests: CFLAGS += $(TARGET)
tests: $(TESTS)
sh ./tests/runtests.sh
valgrind:
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
# The Cleaner
clean:
rm -rf build $(OBJECTS) $(TESTS)
rm -f tests/tests.log
find . -name "*.gc*" -exec rm {} \;
rm -rf `find . -name "*.dSYM" -print`
# The Install
install: all
install -d $(DESTDIR)/$(PREFIX)/lib/
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
# The Checker
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
check:
@echo Files with potentially dangerous functions.
@egrep $(BADFUNCS) $(SOURCES) || true