Makefile - 命令中的命令?

时间:2015-07-06 12:28:03

标签: makefile

我有一个令人尴尬的简单makefile问题,但由于缺乏知识,我无法进行谷歌搜索 - 我不知道我不知道的事情的字样。

基本上,我想在当前目录中运行makefile,查看./SRC目录中的源文件,一切都完成后,将目标文件移动到./OBJ目录中。

生成文件:

move_obj: 
    mv -f -t ./OBJ_DIR ./$(OBJ_FILES)

file.o: other_file.h 
    $(CC) $(CFLAGS) $(CPPFLAGS) -c file.c
    move_obj

我想打电话给" move_obj"编译源文件后,因为我不知道

result: dependency
    evaluation

实际上代表(以及所有的makefile介绍指南我已经找到状态"这就是makefile的样子,然后你就去了#34;),我不会'不知道为什么这不起作用。我假设我需要一些评估命令或需要定义一个函数或......?

提前感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

您可以通过创建另一个move例如all: $(EXECUTABLE) move $(EXECUTABLE): $(OBJECTFILES) $(CC) -o $@ $< $(OBJECTFILES): $(SOURCEFILES) $(CC) $(CFLAGS) -c -o $@ -I $(INCLUDE_PATH) $< # Move the .o to Object directory # move: $(MV) $(OBJECTFILES) $(OBJECT_PATH) 来完成此操作,如下所示

.o

但通过以上操作,您将击败Makefile的目的 由于您的规则取决于Make.o会在当前目录中查找./obj而找不到它(因为您已移动它)并因此重建。

为了避免这种情况,您应该将其输出到gcc -g -Wall -o obj/foo.o -c src/foo.c -I ./include gcc -g -Wall -o obj/main.o -c src/main.c -I ./include gcc -o exe obj/foo.o obj/main.o -lanylibrary 目录并从那里使用它 像

这样的东西
C_FLAGS := -g -Wall -Wextra
CC := gcc
RM := rm
LINKFLAGS := -lanylibrary

.PHONY: $(TARGET) clean

VPATH:= ./src/ ./obj/ ./include/

# Path for .c , .h and .o Files 
SRC_PATH := ./src/
OBJ_PATH := ./obj/
INC_PATH := -I ./include

# Executable Name 
TARGET := exe

# Files to compile
OBJ1 := foo.o \
        main.o

OBJ := $(patsubst %,$(OBJ_PATH)%,$(OBJ1))

# Build .o first
$(OBJ_PATH)%.o: $(SRC_PATH)%.c
                @echo [CC] $<
                @$(CC) $(C_FLAGS) -o $@ -c $< $(INC_PATH)                  

# Build final Binary
$(TARGET):      $(OBJ)
                @echo [INFO] Creating Binary Executable [$(TARGET)]
                @$(CC) -o $@ $^ $(LINKFLAGS)

# Clean all the object files and the binary
clean:   
                @echo "[Cleaning]"
                @$(RM) -rfv $(OBJ_PATH)*
                @$(RM) -rfv $(TARGET)

下面是makefile做同样的事情。

Makefile

有关更好的理解,请参阅此answer

修改
您还可以将可执行文件输出到目录,将以下更改添加到bin 确保预先创建clean目录,而不是# Path for .c , .h and .o Files, and ./bin directory BIN_PATH := ./bin # Executable Name TARGET := $(BIN_PATH)/exe # Clean all the object files and the binary clean: @echo "[Cleaning]" @$(RM) -rfv $(OBJ_PATH)* @$(RM) -fv $(TARGET) 删除。

{{1}}

答案 1 :(得分:1)

如果要在另一个(file.o)之后构建目标(move_obj),请将move_obj添加到file.o的依赖项列表中,以便{{1}下的命令1}}将被执行。

所以你的move_obj应该是:

Makefile

作为评论部分中提到的file.o: other_file.h move_obj $(CC) $(CFLAGS) $(CPPFLAGS) -c file.c move_obj: mv -f -t ./OBJ_DIR ./$(OBJ_FILES) ,您可以在所需目录中构建目标文件,而不是编译然后移动

Colonel Thirty Two

答案 2 :(得分:1)

这有各种各样的缺陷。

  1. result通常是执行配方后应该存在的实际文件。如果该文件已经存在并且不比其任何依赖项旧,则make不会执行任何操作。因此,不要在某处创建文件,然后使用其他规则移动它,请确保规则创建它应该最终的位置。否则make永远无法检查是否必须重建它(并且总是会)。在这种情况下,使用编译器的-o标志直接创建它应该的位置(例如-o $(OBJ_DIR)/file.o

  2. dependency应该列出构建result所需的所有文件,因此如果这些文件中的任何文件发生更改,make会真正重建它。在您的情况下,依赖项列表中至少缺少file.c

  3. 为了将文件放在目录中,您应该确保它存在。你可以这样做:

    $(OBJ_DIR):
        mkdir -p $(OBJ_DIR)
    
    $(OBJ_DIR)/file.o: $(OBJ_DIR) file.c other_file.h
        $(CC) $(CFLAGS) $(CPPFLAGS) -c file.c -o $(OBJ_DIR)/file.o
    
  4. 您的move_obj配方虽然在这种情况下不合适,但却是PHONY目标,这意味着它不会创建文件。如果您需要此类规则,请将它们作为特殊目标.PHONY的依赖关系进行相应标记:

    .PHONY: move_obj
    

    原因是你可以(偶然)在你的工作目录中有一个名为move_obj的文件。在这种情况下,make会决定move_obj没什么可做的,这不是你想要的。将其标记为虚假告诉使该规则不会创建其目标,无论如何都必须执行配方。

  5. 总而言之,你的问题归结为将Makefile误解为一种脚本。它不是。它是一个声明性文件,告诉make为了构建文件(你的evaluation块)需要做什么以及什么时候需要这样做(你的dependency块)。最好不要将Makefile误用为脚本。