C 使用make文件编译单独目录中的文件

C 使用make文件编译单独目录中的文件,c,makefile,C,Makefile,好吧,我从来没有掌握过make和makefile。我尝试过阅读手册,但没有成功。所以我来到这里:我 我有一堆文件开始在一个文件中变得非常不受管理。(我正在尝试制作一个操作系统),我想尝试将这些文件分割成单独的子目录(见下面的结构),然后告诉make将这些文件“制作”成一个它们的.o文件,将它们移动到另一个单独的子目录,最后得到一个内核文件。(如果这听起来很复杂,很抱歉,希望结构能让事情变得更清楚) 这是我想要的结构树: Pare

好吧,我从来没有掌握过make和makefile。我尝试过阅读手册,但没有成功。所以我来到这里:我

我有一堆文件开始在一个文件中变得非常不受管理。(我正在尝试制作一个操作系统),我想尝试将这些文件分割成单独的子目录(见下面的结构),然后告诉make将这些文件“制作”成一个它们的.o文件,将它们移动到另一个单独的子目录,最后得到一个内核文件。(如果这听起来很复杂,很抱歉,希望结构能让事情变得更清楚)

这是我想要的结构树:

                                  Parent directory 
                           ( where the makefile will be )
                                          |
                                          |
     -------------------------------------------------------------------------
     |                 |                  |                |                 |
  Header SubDir      Source SubDir      ASM SubDir      Obj SubDir        Kern SubDir
(Header files )     (Source Files)     (Assembly Files)  (Object Files)   (Kernel File)
这是我当前的生成文件:

C_SOURCES= main.c
S_SOURCES= boot.s
C_OBJECTS=$(patsubst %.c, obj/%.o, $(C_SOURCES))
S_OBJECTS=$(patsubst %.s, obj/%.o, $(S_SOURCES))
CFLAGS=-nostdlib -nostdinc -fno-builtin -fno-stack-protector -m32 -Iheaders
LDFLAGS=-Tlink.ld -melf_i386 --oformat=elf32-i386
ASFLAGS=-felf

all: kern/kernel

.PHONY: clean
clean:
-rm -f kern/kernel

kern/kernel: $(S_OBJECTS) $(C_OBJECTS)
ld $(LDFLAGS) -o $@ $^

$(C_OBJECTS): obj/%.o : %.c 
gcc $(CFLAGS) $<

vpath %.c source

$(S_OBJECTS): obj/%.o : %.s
nasm $(ASFLAGS) $<

vpath %.s asem
提前谢谢你的帮助


杰米

让我们分阶段进行:

all: $(SOURCES) link
您不必构建源代码,所以我们不必这样做。您真正想要构建的是
kern/kernel
,所以让我们用它来代替抽象的“链接:

但是您希望链接对象文件,而不是源文件,并在
kern/
中生成
kernel
,而不是在父目录中(我假设您将在父目录中运行
make
):

那么对象是什么呢?我假设源是
.s
文件,对象具有相同的名称,但后缀不同,位置也不同:

SOURCES=boot.s main.s monitor.s common.s descriptor_tables.s isr.s interrupt.s gdt.s timer.s kheap.s paging.s

OBJECTS=$(patsubst %.s,Obj/%.o,$(SOURCES))
这就是制作对象的方法:

$(OBJECTS): Obj/%.o : %.s
    nasm $(ASFLAGS) $<

vpath %.s Src

你试图一次做很多事情,所以第一次尝试可能不起作用。试一试,让我们知道结果。

相关:Pavan Manjunath可能重复不,这不是重复,它与那篇文章有点关系,但我做的完全不同。bitmask我如何编写makefile来编译和链接source位于不同子目录中的文件?您从未设置
对象
——您可能需要
对象=$(C\u对象)$(S\u对象)
@chrisdod谢谢,你知道为什么上面仍然会出现新的错误吗?源代码是.s和.c的混合,所以我想我会把sources=boot.s…等改为相关后缀?@jamiedwards,在你的问题中提到这一点会很好。最简单的方法是使用
c_源代码
s_源代码
,还有
C_对象
S_对象
,以及编译
C
文件的规则。我最诚挚的歉意。我应该把文件的后缀放在:L noobish thing to do。刚刚用我的新makefile更新了OP,它吐出了我也编辑过的错误。有什么想法吗?使用
$(S_对象)
而不是
$(对象)
kern/kernel: $(OBJECTS)
    ld $(LDFLAGS) -o $@ $^
SOURCES=boot.s main.s monitor.s common.s descriptor_tables.s isr.s interrupt.s gdt.s timer.s kheap.s paging.s

OBJECTS=$(patsubst %.s,Obj/%.o,$(SOURCES))
$(OBJECTS): Obj/%.o : %.s
    nasm $(ASFLAGS) $<

vpath %.s Src
.PHONY: clean
clean:
    -rm -f Obj/*.o kern/kernel