繁体   English   中英

Makefile-命令中的命令?

[英]Makefile - a command in a command?

我有一个尴尬的简单makefile问题,但由于缺乏知识而无法在Google上搜索-我不知道那些我不知道的单词。

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

Makefile文件:

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的样子,然后就走了”),我不知道为什么这不起作用。 我假设我需要一些评估命令或需要定义一个函数或...?

感谢您的任何帮助。

您可以通过创建另一个rule (例如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)

但是,通过执行上述操作,您将无法达到Makefile的目的
由于您的规则取决于.o ,因此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

下面是做同样的makefile文件。

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
确保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)

如果要在另一个(file.o)之后构建目标( move_obj ),则将move_obj添加到file.o的依赖项列表中,以便将执行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 ,您可以在所需目录中构建目标文件,而不是先编译然后再移动。

file.o: other_file.h
    $(CC) $(CFLAGS) $(CPPFLAGS) -c file.c -o ./$(OBJ_FILES)/$@

这有各种缺陷。

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

  2. dependency应列出生成result所需的所有文件, 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

     .PHONY: move_obj 

    这样做的原因是,您可能(偶然)在工作目录中有一个名为move_obj的文件。 在这种情况下,make会决定对move_obj不执行任何操作,而这不是您想要的。 将其标记为phony可以表明该规则不会创建其目标,并且无论如何都必须执行配方。

总而言之,您的问题归结为对Makefile的理解是一种脚本。 它不是。 它是一个说明性文件,告诉make必须执行什么操作才能构建文件(您的evaluation块)以及何时需要执行此操作(您的dependency块)。 最好不要尝试将Makefile用作脚本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM