3

我正在尝试使用 Zed Shaw 的 Learn 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”有什么区别?是否有方便的命令列表可以帮助我更好地理解如何正确生成生成文件?

谢谢你的时间。

4

2 回答 2

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 编译的)。

虽然我不完全理解我的解决方案,但它至少让我能够毫无错误地编译和运行程序。希望这个解决方案会引起其他人的兴趣,也许更有知识的人能够更详细地解释它为什么起作用。

于 2013-06-26T05:03:01.270 回答
3

来自GNU Make Manual10.2 隐式规则目录

通过 C 编译器运行链接器(通常称为)来
n自动链接单个目标文件。使用的精确配方是“ ”。n.old$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)

如您所见,LDFLAGS在您的目标文件之前和LDLIBS之后。有时该顺序可能很重要 - 显然在您的情况下确实如此。

编者注:虽然有时使用 make 的隐式规则支持可能很方便,但它几乎总是在以后变得更加混乱。我敦促您编写一个完整的 makefile - 它可以帮助您更好地了解正在发生的事情,并希望将来避免此类问题。

于 2013-03-01T19:42:22.843 回答