TL; DR:我正在开展一个dlfcn.h
用于打开共享库的C练习.尽管添加(我认为是)基于其他帖子的正确标志,我仍然会收到undefined reference to
错误dlopen
,dlsym
并且在其中定义了一些其他函数dlfcn.h
(错误消息和make文件包含在下面).
我在.c
文件的开头包括以下内容:#include
我究竟做错了什么?
详细版本:
我正在进行练习30,Learn C The Hard Way
并且我很困惑我还需要做什么才能使libex29_tests.c
程序(页面上的最后一段代码)正确编译.您可能已经知道,共享库/ makefile /编译器标志对我来说是新的.
到目前为止我尝试过的内容:基于以下帖子,我尝试-ldl
通过添加LIBS=-ldl fPIC
和/或添加LDFLAGS+=-ldl
到Makefile的各个部分来添加标记,但仍然存在问题.书中的makefile版本(包含在下面,作为参考)确实包含一个-ldl
标志,尽管语法略有不同.无论如何,我继续得到相同的错误消息.
Linux c ++错误:对'dlopen'的未定义引用
即使使用-ldl标志,g ++也无法链接到libdl
在安装phonetisaurus时未定义引用'dlopen'
C++:使用dlopen()加载共享库时未定义的符号
有什么建议?
这些是我得到的错误.这些错误假定makefile
下面包含的版本.但是,正如我所提到的,更改-ldl
标志的语法会导致几乎相同的错误消息.
~/.../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
这是makefile
本书的最新内容.它确实包括-ldl
标志,你可以在第二行看到.
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
ensc.. 6
${LIBS}
(和你的-ldl
)在makefile中没有使用.看来,您正在使用内置规则进行编译,并且可以使用LDLIBS
而不是LIBS
此变量的名称.
除此之外,还有
tests: CFLAGS += $(TARGET)
在你的例子中是错误的,因为它TARGET
是一个必须进入的库(LD)LIBS
.
$(TARGET): build $(OBJECTS) build: @mkdir -p build
也不健全.这将打破并行构建($(OBJECTS)
应该依赖build
)并将导致不需要的构建(build
是一个目录并由每个编译/链接操作更改).平原build
对于VPATH
构建会有问题,我建议使用
$(OBJECTS): | build/.dirstamp build/.dirstamp: mkdir ${@D}
这里.
${LIBS}
(和你的-ldl
)在makefile中没有使用.看来,您正在使用内置规则进行编译,并且可以使用LDLIBS
而不是LIBS
此变量的名称.
除此之外,还有
tests: CFLAGS += $(TARGET)
在你的例子中是错误的,因为它TARGET
是一个必须进入的库(LD)LIBS
.
$(TARGET): build $(OBJECTS) build: @mkdir -p build
也不健全.这将打破并行构建($(OBJECTS)
应该依赖build
)并将导致不需要的构建(build
是一个目录并由每个编译/链接操作更改).平原build
对于VPATH
构建会有问题,我建议使用
$(OBJECTS): | build/.dirstamp build/.dirstamp: mkdir ${@D}
这里.