zedshaw / learn-c-the-hard-way-lectures

All of the code from Learn C The Hard Way, each project, plus the presentation slides used in the videos.
Other
1.23k stars 483 forks source link

Ex28: C-skeleton Makefile fails to link the dl library #43

Open TylersGit opened 4 months ago

TylersGit commented 4 months ago

When using the Makefile from the book/repo, the dl library is not linked, causing compilation to fail due "undefined reference to ". Relevant log:

[root@localhost exercise29]# make all
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG  -fPIC   -c -o src/libex29.o src/libex29.c
ar rcs build/libex29.a src/libex29.o
ranlib build/libex29.a
cc -shared -o build/libex29.so src/libex29.o
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG  build/libex29.a    tests/ex29_tests.c   -o tests/ex29_tests
/tmp/cc6B8uPY.o: In function `main':
/root/exercise29/tests/ex29_tests.c:16: undefined reference to `dlopen'
/root/exercise29/tests/ex29_tests.c:20: undefined reference to `dlsym'
/root/exercise29/tests/ex29_tests.c:29: undefined reference to `dlclose'
/root/exercise29/tests/ex29_tests.c:17: undefined reference to `dlerror'
/root/exercise29/tests/ex29_tests.c:21: undefined reference to `dlerror'
collect2: error: ld returned 1 exit status
make: *** [tests/ex29_tests] Error 1

Looking at the output, we can see that the -ldl flag is not added to the compilation command. Changing line 2 in the Makefile from LIBS to LDLIBS solves that problem, and ex29_tests gets compiled properly.

[root@localhost exercise29]# make all
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG  -fPIC   -c -o src/libex29.o src/libex29.c
ar rcs build/libex29.a src/libex29.o
ranlib build/libex29.a
cc -shared -o build/libex29.so src/libex29.o
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG  build/libex29.a    tests/ex29_tests.c  -ldl  -o tests/ex29_tests
sh ./tests/runtests.sh
[root@localhost exercise29]# 
zhuguiyuan commented 6 days ago

It's due to the arguments order of build/libex29.a and tests/ex29_tests.c. You can write Makefile like this:

# The Unit Tests
.PHONY: tests
$(TESTS): $(TARGET)
tests: $(TESTS)
        sh ./tests/runtests.sh