在 C 语言中,如何使用 "make functionName" 这样的 makefile 只编译一个函数(需要来自自定义库的函数)?

In C, how do I compile only one function (that requires functions from a custom library) using a makefile like so "make functionName"?

我正在创建一个函数库,我想使用 Makefile 一次测试一个函数。我在一个函数中写了一个 main 来单独测试它。我想 运行 make hello 一个名为 hello.c 的文件,我希望输出被命名为 hello 我可以 运行 使用 ./hello.

生成文件:

NAME = libnt.a

CC = gcc -Wall -Werror -Wextra

SRC = fputchar.c fputstr.c hello.c

OBJ = $(SRC:%.c=%.o)

HDR = libnt.h

${NAME}:
    ${CC} -c -L${HDR} ${SRC}
    ar rcs ${NAME} ${OBJ}
    ranlib ${NAME}

: .c ${NAME}
    ${CC} .c ${NAME} -o 

libnt.h:

#ifndef HELLO_H
#define HELLO_H
#include <unistd.h>

void fputchar(int c);
void fputstr(char s[]);
void hello(void);

#endif

hello.c:

#include "libnt.h"

void hello(void)
{
    fputstr("Hello");
}

int main(void)
{
    hello();
    return (0);
}

如您所见,hello 函数需要 fputstr 函数和 fputstr函数需要 fputchar 函数但是当我 运行 make hello:

$ make hello
gcc     hello.c   -o hello
/tmp/ccczcfiM.o: In function `hello':
hello.c:(.text+0xc): undefined reference to `fputstr'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'hello' failed
make: *** [hello] error 1

我怀疑 libnt.a 没有被编译,但我把它作为 规则依赖项之一,正如你在 Makefile 中看到的那样,所以它应该先编译然后继续 规则操作。请注意 $ make hello 之后的行中的空格,我认为这意味着 ${NAME} 没有得到扩展。 运行 make 完美运行。

你的 Makefile 有四个主要问题,假设它被 GNU Make 使用。

  1. 你没有正确构建库——它必须依赖于目标文件,并且是从目标文件而不是源代码构建的(如果你这样做正确,那么内置规则将处理构建目标文件)。

  2. 您构建测试程序的规则不正确 -- 您似乎在尝试使用函数参数变量而不是正确的模式规则。

  3. 你的目标文件不依赖于你的头文件

  4. 测试的来源,例如hello.c,不应列在SRCS

也有一些小问题,包括您很容易混淆 make 和 shell 变量与 ${}

像下面这样的东西应该更适合你(同样,假设你使用 GNU Make):

LIB = nt

override CFLAGS += -W -Wall -Werror -Wextra

SRCS = fputchar.c fputstr.c
OBJS = $(SRCS:%.c=%.o)

HDR = libnt.h

lib$(LIB).a: $(OBJS)
    $(AR) $(ARFLAGS) $@ $^
    ranlib $(@)

$(OBJS): $(HDR)

override LDFLAGS += -L.

# a pattern rule to make test programs for the library
%: %.c lib$(LIB).a
    $(LINK.c) $@.c -o $@ -l$(LIB)

编辑:

抱歉,我违反了我自己的规则,即不完全测试我发布的内容(复制和粘贴对于完全独立的工作和浏览器环境来说并不总是微不足道的)。

我的第一次尝试至少遇到了三个问题:

  1. 我不小心重置了默认目标,将头文件的依赖项放在库的目标之上。

  2. GNU Make 没有定义$(RANLIB)

  3. 我不小心将模式规则更改为依赖于匹配的 .o 文件而不是 .c

我还更改了 *FLAGS 设置以使用带有 +=override 指令,以允许保留任何系统默认值或命令行指定的值,并让 Makefile 仅添加附加标志。

你的原件中还有一个额外的问题,我的第一次尝试没有解决:测试的来源(例如 hello.c)不应该包含在 SRCS 列表中,因为你这样做了不希望 its/their 个对象包含在库中。如果您想出于其他原因列出这些来源,请在单独的变量中列出。

要回答您评论中的问题:依赖关系是按递归顺序构建的,每个依赖关系的规则在每个依赖于它们的目标之前 运行,因此在此示例中,所有 OBJS 都是首先构建(使用内置规则),因为库依赖于它们,然后构建它,因为它是默认目标,或者因为您在命令文件中指定了一个程序目标并且依赖于库(及其自己的源文件)。