我正在努力学习使用Zed Shaw的学习C的C编程。我一直在研究ex26,我们创建了一个用于安装软件的程序“devpkg”。此练习需要安装Apache Portable Runtime库。在为本练习编写代码之后,我无法使用以下makefile编译程序:
PREFIX?=/user/local
CFLAGS=-g -Wall -I${PREFIX}/apr/include/apr-1 -I{PREFIX}/apr/include/apr-util-1
LDFLAGS=-L${PREFIX}/apr/lib -lapr-1 -pthread -laprutil-1
all: devpkg
install: all
install -d${DESTDIR}/${PREFIX}/bin/
install devpkg ${DESTDIR}/${PREFIX}/bin/
clean:
rm -f *.o
rm -f devpkg
rm -f *.dSYM
这个makefile似乎不起作用,因为我使用“$ make devpkg”时并未声明所有APR库函数。作为旁注,我在Ubuntu虚拟机上运行它。文中给出的解决方案是更改配置文件,然后“运行ldconfig”以帮助链接器找到合适的库。
我不太了解ldconfig的手册页,以便正确使用该函数。如何正确运行ldconfig?
经过一些挖掘后,我发现在makefile中使用“LDLIBS”代替“LDFLAGS”的引用修复了问题。我修改了makefile和编译的程序。
允许C编译器正确链接到APR库的“LDFLAGS”和“LDLIBS”之间有什么区别?是否有一个方便的命令列表可以帮助我更好地理解如何正确生成makefile?
感谢您的时间。
答案 0 :(得分:3)
来自GNU Make Manual, 10.2隐含规则目录:
链接单个目标文件
n
是通过运行链接器(通常称为n.o
)从ld
自动生成的C编译器。使用的精确配方是“$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
”。
如您所见,LDFLAGS
位于您的目标文件之前,LDLIBS
位于之前。有时候这个命令很重要 - 显然在你的情况下确实如此。
编者注:尽管使用make的隐式规则支持有时候很方便,但它几乎总是会让人感到更加混乱。我敦促你写一个完整的makefile - 它会帮助你更好地理解发生了什么,并希望将来避免这类问题。
答案 1 :(得分:3)
我只想添加此答案作为将“LDFLAGS”更改为“LDLIBS”的替代方法。上面的解决方案确实适用于我的情况,但在我看到其他人可能觉得有用或有趣之前,我找到了另一种解决方案(虽然不那么直接)。在编译时,我看到了许多“未定义的引用”错误,例如:
/MyCode/LCTHW/devpkg/devpkg.c:18: undefined reference to `apr_pool_initialize'
经过多次试验和错误,我改变了makefile(仍然使用LDFLAGS):
CC=gcc
PREFIX?=/usr/local
CFLAGS=-g -Wall -I$(PREFIX)/apr/include/apr-1 -I$(PREFIX)/apr/include/apr-util-1
LDFLAGS=-L$(PREFIX)/apr/lib -lapr-1 -laprutil-1 -pthread
OBJECTS=bstrlib.o db.o shell.o commands.o devpkg.o
all: devpkg
devpkg: $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o devpkg $(LDFLAGS)
install: all
install -d $(DESTDIR)/$(PREFIX)/bin/
install devpkg $(DESTDIR)/$(PREFIX)/bin/
clean:
rm -f *.o
rm -f devpkg
rm -rf *.dSYM
然后,我必须将.conf文件添加到/etc/ld.so.conf.d,其中包含apr库的路径,即
/usr/local/apr/lib
然后运行
sudo ldconfig
所以系统会选择新的.conf文件,因此知道在哪里找到库。从我所看到的,似乎最后一步是必要的,因为库没有存储在/ usr / local / lib中。如果我删除了.conf文件并重新运行ldconfig进行更新,程序将编译但无法在运行时找到库(无论是使用我的makefile还是使用OP编译)。
虽然我不完全理解我的解决方案,但它至少允许我编译并运行程序而没有错误。希望这个解决方案会让其他人感兴趣,也许更有知识的人能够更详细地解释它为什么会起作用。