如何从目录中读取源文件并将目标文件创建到生成文件中的另一个文件夹中?

How do I read source files from a directory and create object files into another folder in a makefile?

我有以下源文件:

% ls 
data_lexicon.c  data_lexicon.h  lex.l           makefile

以及以下生成文件:

% cat makefile
CC              = cc
CFLAGS          = -Wall -std=c89
LDFLAGS         = -ll
OBJFILES        = lex.o data_lexicon.o
TARGET          = lexical_analyzer_1

all:            $(TARGET) lex.c

lex.c:          lex.l data_lexicon.h
                lex -olex.c lex.l

$(TARGET):      $(OBJFILES)
                $(CC) $(CFLAGS) -o $(TARGET) $(OBJFILES) $(LDFLAGS)

clean:
                rm -f $(OBJFILES) lex.c $(TARGET)

如果我这样做 make all 我得到:

% ls 
data_lexicon.c          data_lexicon.o          lex.l
lexical_analyzer_1      data_lexicon.h          lex.c
lex.o                   makefile

到目前为止一切顺利。

但是,我想将源文件 (data_lexicon.c、data_lexicon.h、lex.l) 移动到文件夹 src 并生成中间文件 (data_lexicon.o lex.c, lex.o) 到 obj 文件夹。

我创建了两个文件夹,但我不明白如何配置 makefile 文件。

我正在使用 FreeBSD make,所以给出的解决方案越便携越好。

However, I would like to move the source files (data_lexicon.c, data_lexicon.h, lex.l) to a folder src and generate the intermediate files (data_lexicon.o lex.c, lex.o) into a obj folder.

人们总是坚持为自己做额外的工作,这让我感到惊讶。您当然可以按照您的描述进行操作,但这需要为目标文件编写明确的规则。

然而,首先,您需要了解 make 本身并不真正了解目录。 (无论如何,传统的 make 没有。GNU make 和其他人可能对它们知之甚少 。)也就是说,它没有任何意义它解析文件名的不同目录。相反,每个目标名称都根据 make 的工作目录进行解析。如果你想引用子目录中的东西,那么你必须这样说。开始于:

OBJFILES        = obj/lex.o obj/data_lexicon.o

规则中的目标和先决条件名称类似:

obj/lex.c:      src/lex.l src/data_lexicon.h
                lex -o$@ src/lex.l

这也是支持 make 的自动变量的原因之一,例如上述规则中的 $@ 表示正在构建的目标的名称。

您的 makefile 目前依赖 make 从相应的 C 源文件构建目标文件的内置规则,但“相应”意味着目标和先决条件名称相同,包括任何路径组件,后缀除外(.c vs .o)。您将不再拥有 data_lexicon.o 的对应关系,因此您需要为其构建它编写明确的规则。这部分留作练习。