I'm following the "Learn C the Hard Way" ebook(?), and reached exercise 32.
It uses a previously developed project structure, where tests link to the built library. However, when I run make test
, I get "undefined reference to X", where X is every function defined in my library's header.
twoll_tests.c
is my test file, libds
is the library. See project tree at the bottom of this question.
The compilation line for the tests is this:
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG -std=c11 build/libds.a tests/twoll_tests.c -o tests/twoll_tests
Makefile contents:
CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG -std=c11 $(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/libds.a SO_TARGET=$(patsubst %.a,%.so,$(TARGET)) # The Target Build all: $(TARGET) $(SO_TARGET) 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: test test: CFLAGS += $(TARGET) test: $(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
And finally, the project tree:
. ├── bin ├── build │ ├── libds.a │ └── libds.so ├── LICENSE ├── Makefile ├── README.md ├── src │ └── libds │ ├── twoll.c │ ├── twoll.h │ └── twoll.o └── tests ├── runtests.sh ├── tester.h ├── tests.log └── twoll_tests.c
EDIT: Here's the full output of make test
:
kroltan@kroltan ~/Projects/learncthehardway/ex32 $ make all cc -g -O2 -Wall -Wextra -Isrc -rdynamic -std=c11 -fPIC -c -o src/libds/twoll.o src/libds/twoll.c ar rcs build/libds.a src/libds/twoll.o ranlib build/libds.a cc -shared -o build/libds.so src/libds/twoll.o kroltan@kroltan ~/Projects/learncthehardway/ex32 $ make test cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG -std=c11 build/libds.a tests/twoll_tests.c -o tests/twoll_tests /tmp/ccnOW9OX.o: In function `twoll_new_test': /home/kroltan/Projects/learncthehardway/ex32/tests/twoll_tests.c:8: undefined reference to `twoll_new' /tmp/ccnOW9OX.o: In function `twoll_del_test': /home/kroltan/Projects/learncthehardway/ex32/tests/twoll_tests.c:13: undefined reference to `twoll_new' /home/kroltan/Projects/learncthehardway/ex32/tests/twoll_tests.c:13: undefined reference to `twoll_del' /tmp/ccnOW9OX.o: In function `twoll_push_pop_test': /home/kroltan/Projects/learncthehardway/ex32/tests/twoll_tests.c:18: undefined reference to `twoll_new' /home/kroltan/Projects/learncthehardway/ex32/tests/twoll_tests.c:18: undefined reference to `twoll_push' /home/kroltan/Projects/learncthehardway/ex32/tests/twoll_tests.c:18: undefined reference to `twoll_push' /home/kroltan/Projects/learncthehardway/ex32/tests/twoll_tests.c:18: undefined reference to `twoll_push' /home/kroltan/Projects/learncthehardway/ex32/tests/twoll_tests.c:18: undefined reference to `twoll_pop' /home/kroltan/Projects/learncthehardway/ex32/tests/twoll_tests.c:18: undefined reference to `twoll_pop' /home/kroltan/Projects/learncthehardway/ex32/tests/twoll_tests.c:18: undefined reference to `twoll_pop' collect2: error: ld returned 1 exit status make: *** [tests/twoll_tests] Error 1