我有这个Makefile:
CFLAGS = -ffreestanding -O2 -nostdlib -lgcc
BUILD_DIR = ../build
BIN = $(BUILD_DIR)/os.bin
LINKER_SCRIPT = linker.ld
OBJ_FILES := $(shell find $(BUILD_DIR) -iname '*.o')
.PHONY: all
all:
@make -C boot
@make -C kernel
$(CC) -T $(LINKER_SCRIPT) -o $(BIN) $(CFLAGS) $(OBJ_FILES)
编译后(在引导目录和内核目录中进行制作),应该具有扩展名为.o的文件,但是OBJ_FILES为空。只有在再次调用make之后,OBJ_FILES才包含链接所需的.o文件路径。因此,我的问题是在引导目录和内核目录中进行编译后如何更新OBJ_FILES,因为OBJ_FILES不会更新/刷新。
答案 0 :(得分:0)
假设您具有以下结构:
.
|-- Makefile
|-- boot
| |-- Makefile
| |-- boot.c
| `-- boot.h
|-- kernel
| |-- Makefile
| |-- kernel.c
| `-- kernel.h
`-- main.c
您的Makefile
如下
location = $(CURDIR)
OBJ_FILES = $(shell find $(location) -name '*.o')
all: make_common
gcc -o main main.c $(OBJ_FILES)
make_common:
@make -C boot
@make -C kernel
clean:
-rm boot/boot.o
-rm kernel/kernel.o
您的源代码非常简单:
> cat boot/boot.h
int boot();
> cat boot/boot.c
int boot() {
return 1;
}
> cat kernel/kernel.h
int kernel();
> cat kernel/kernel.c
int kernel() {
return 2;
}
> cat main.c
#include "boot/boot.h"
#include "kernel/kernel.h"
int main() {
int result = boot() + kernel();
return 0;
}
“内部” Makefile
包含
> cat boot/Makefile
all:
gcc -c boot.c
> cat kernel/Makefile
all:
gcc -c kernel.c
您将得到想要的东西
> make clean
rm boot/boot.o
rm: boot/boot.o: No such file or directory
make: [clean] Error 1 (ignored)
rm kernel/kernel.o
rm: kernel/kernel.o: No such file or directory
make: [clean] Error 1 (ignored)
> make
gcc -c boot.c
gcc -c kernel.c
gcc -o main main.c ..../boot/boot.o ..../kernel/kernel.o
VAR = val
使用变量时扩展。
答案 1 :(得分:0)
所以我的问题是在引导目录和内核目录中编译后如何更新
OBJ_FILES
,因为OBJ_FILES
不会更新/刷新。
OBJ_FILES
变量一旦开始执行规则就不会更改其值。
有关详细信息,请参见3.7 How make Reads a Makefile:
GNU make在两个不同的阶段进行工作。在第一个阶段,它读取所有makefile,包括的makefile等,并内化所有变量及其值以及隐式和显式规则,并构建所有目标及其前提条件的依赖图。在第二阶段中,make使用此内部化数据来确定需要更新哪些目标,并运行更新目标所需的配方。
理解这种两阶段方法很重要,因为它会直接影响变量和函数扩展的发生方式;编写makefile时,这通常会引起一些混乱。
相反,您可以做的是一旦make
构建内核并启动后重新启动:
all: $(BIN)
$(BIN) : $(OBJ_FILES)
$(CC) -T $(LINKER_SCRIPT) -o $@ $(CFLAGS) $(OBJ_FILES)
Makefile :
@$(MAKE) -C boot
@$(MAKE) -C kernel
touch $@ # <---- Causes the Makefile to be re-read.
.PHONY: all