Makefile:根据目标在构建对象之前更改变量。

huangapple go评论59阅读模式
英文:

Makefile: changing variables based on target before building objects

问题

我想让我的Makefile能够根据目标使用不同的标志/编译器进行编译:

SRC := .
OBJ := .
SOURCES := $(wildcard $(SRC)/*.c)
OBJECTS = $(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(SOURCES))
BINARY := hello_world

all: $(BINARY)

$(BINARY):
  $(CC) $(LDFLAGS) $(OBJECTS) -o $@

$(OBJ)/%.o: $(SRC)/%.c
  $(CC) $(CFLAGS) -I$(SRC) -c $< -o $@

bm: $(OBJECTS)
  $(eval CC := aarch64-none-elf-gcc)
  $(eval CFLAGS += -DBAREMETAL)
  $(eval CFLAGS += -ffreestanding)

linux: $(OBJECTS)
  $(eval CC := aarch64-none-linux-gnu-gcc)

问题在于,因为每个目标都依赖于$(OBJECTS)(我需要编译这些对象),所以在评估之前设置CC变量的行未设置。因此,当我编译时:

> make bm -n
cc hello_world.o -o hello_world

而不是使用我指定的编译器和标志。有没有推荐的Makefile结构可以使这个工作?

英文:

I would like my Makefile to be able to compile with different flags/compiler depending on the target:

SRC := .
OBJ := .
SOURCES := $(wildcard $(SRC)/*.c)
OBJECTS = $(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(SOURCES))
BINARY := hello_world

all: $(BINARY)

$(BINARY):
  $(CC) $(LDFLAGS) $(OBJECTS) -o $@

$(OBJ)/%.o: $(SRC)/%.c
  $(CC) $(CFLAGS) -I$(SRC) -c $&lt; -o $@

bm: $(OBJECTS)
  $(eval CC := aarch64-none-elf-gcc)
  $(eval CFLAGS += -DBAREMETAL)
  $(eval CFLAGS += -ffreestanding)

linux: $(OBJECTS)
  $(eval CC := aarch64-none-linux-gnu-gcc)

The issue here is that since each target depends on $(OBJECTS) (which I need to compile the objects) the lines that set the CC variable do not get set before evaluating. Thus, when I compile:

&gt; make bm -n
cc hello_world.o -o hello_world

Instead of using the compiler and flags I specified. What's a recommended Makefile structure that would make this work?

答案1

得分: 1

不要尝试在食谱中使用 eval 分配变量。如果要在食谱中使用它们,请使用目标特定的变量值。如果要在前提条件列表中使用它们,请使用条件语句来处理 MAKECMDGOALS(因为显然您正在使用GNU make)或自定义的 make 变量。

示例:

SRC     := .
OBJ     := .
SOURCES := $(wildcard $(SRC)/*.c)
OBJECTS := $(patsubst $(SRC)/%.c,$(OBJ)/%.o,$(SOURCES))
BINARY  := hello_world

.PHONY: all bm linux clean

all bm linux: $(BINARY)

bm: CC := aarch64-none-elf-gcc
bm: CFLAGS += -DBAREMETAL -ffreestanding

linux: CC := aarch64-none-linux-gnu-gcc

$(BINARY): $(OBJECTS)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)

$(OBJ)/%.o: $(SRC)/%.c
    $(CC) $(CFLAGS) -I$(SRC) -c $< -o $@

clean:
    rm -f $(OBJECTS) $(BINARY)

但是请考虑,如果您先运行 make bm,然后再运行 make linuxhello_world 不会重新构建,因为它被视为最新的。一个简单的解决方法是声明一个虚拟的 clean 目标(如上所示),它会删除所有对象文件和 hello_world,并在使用不同编译器和/或编译器选项构建 hello_world 之前运行 make clean

如我在回答您的其他类似问题中所解释的,更干净的方法是拥有两个不同的可执行文件,而不仅仅是一个,还有不同的目标文件。您可以使用不同的 OBJ 值来处理不同的设置。

英文:

Do not try to assign make variables in recipes with eval. Use target-specific variable values if you want to use them in the recipes. Use conditionals on MAKECMDGOALS (as you are apparently using GNU make) or custom make variables if you want to use them in lists of prerequisites.

Example:

SRC     := .
OBJ     := .
SOURCES := $(wildcard $(SRC)/*.c)
OBJECTS := $(patsubst $(SRC)/%.c,$(OBJ)/%.o,$(SOURCES))
BINARY  := hello_world

.PHONY: all bm linux clean

all bm linux: $(BINARY)

bm: CC := aarch64-none-elf-gcc
bm: CFLAGS += -DBAREMETAL -ffreestanding

linux: CC := aarch64-none-linux-gnu-gcc

$(BINARY): $(OBJECTS)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)

$(OBJ)/%.o: $(SRC)/%.c
    $(CC) $(CFLAGS) -I$(SRC) -c $&lt; -o $@

clean:
    rm -f $(OBJECTS) $(BINARY)

But also consider that if you make bm, followed by make linux, hello_world will not be rebuilt because it is considered as up-to-date. An easy solution is to declare a phony clean target (as above) that deletes all object files and hello_world, and doing a make clean before building hello_world with a different compiler and/or compiler options.

An even cleaner way, as I explained in my answer to your other similar question, is to have 2 different executable files instead of just one, and also different object files. You could, for instance, use different OBJ values for your different settings.

huangapple
  • 本文由 发表于 2023年7月7日 05:00:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76632503.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定