简体   繁体   English

Makefile-命令中的命令?

[英]Makefile - a command in a command?

I have an embarrassingly simple makefile question but I can't google it due to lack of knowledge - I don't know the words for things I don't know. 我有一个尴尬的简单makefile问题,但由于缺乏知识而无法在Google上搜索-我不知道那些我不知道的单词。

Basically, I want to run the makefile in the current directory, look into the ./SRC directory for source files and when everything is finished, move the object files into the ./OBJ directory. 基本上,我想在当前目录中运行makefile,在./SRC目录中查找源文件,当一切完成后,将目标文件移至./OBJ目录。

Makefile: Makefile文件:

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

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

I want to call "move_obj" after compiling the source files but since I don't know what 我想在编译源文件后调用“ move_obj”,但是由于我不知道什么

result: dependency
    evaluation

actually represents (and all makefile introduction guides I've found state "This is what a makefile looks like, off you go then"), I don't know why this isn't working. 实际代表(以及我发现的所有makefile介绍指南都指出“这是makefile的样子,然后就走了”),我不知道为什么这不起作用。 I assume I need some evaluate command or need to define a function or...? 我假设我需要一些评估命令或需要定义一个函数或...?

Thanks for any help in advance. 感谢您的任何帮助。

You can do this by creating another rule for example move , like below 您可以通过创建另一个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)

But by doing the above, you will defeat the purpose of the Makefile . 但是,通过执行上述操作,您将无法达到Makefile的目的
Since your rule is dependent on .o , Make will look for .o in current directory and not find it (because you've moved it) and thus rebuild. 由于您的规则取决于.o ,因此Make会在当前目录中查找.o ,但找不到它(因为已将其移动了),因此进行了重建。

To avoid this, you should output it to ./obj directory and use it from there. 为避免这种情况,应将其输出到./obj目录并从那里使用它。
Something like 就像是

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

Below is the makefile doing the same. 下面是做同样的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)

Refer to this answer for a better understanding 请参阅此答案以获得更好的理解

EDIT : 编辑
You can also output your executable to directory, add the following changes to your Makefile . 您还可以将可执行文件输出到目录,将以下更改添加到Makefile
Ensure that the bin directory is created beforehand, and not deleted by clean . 确保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)

If you want to build a target( move_obj ) after another(file.o), add the move_obj to the dependency list of file.o so that the commands under the move_obj will be executed. 如果要在另一个(file.o)之后构建目标( move_obj ),则将move_obj添加到file.o的依赖项列表中,以便将执行move_obj下的命令。

So your Makefile should be: 因此,您的Makefile应该是:

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

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

As Colonel Thirty Two mentioned in the comment section, instead of compiling and then move, you can build the object files in the required directory 正如评论部分中提到的“ Colonel Thirty Two ,您可以在所需目录中构建目标文件,而不是先编译然后再移动。

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

This is flawed in various ways. 这有各种缺陷。

  1. result normally is an actual file that should be present after the recipe is executed. result通常是执行配方后应该存在的实际文件。 If the file is already there and is not older than any of its dependencies, make does nothing. 如果该文件已经存在并且不早于其任何依赖项,则make不执行任何操作。 So instead of creating a file somewhere and then moving it around with another rule, make sure the rule creates it where it should FINALLY be. 因此,不要在某个位置创建文件然后再使用另一条规则来移动它,而是要确保该规则将文件创建在最终应位于的位置。 Otherwise make can never check whether it has to rebuild it (and always will). 否则, make永远无法检查它是否必须重建它(并且永远都会)。 In this case, use the -o flag of the compiler to directly create it where it should be (eg -o $(OBJ_DIR)/file.o ) 在这种情况下,请使用编译器的-o标志直接在应有的位置创建它(例如-o $(OBJ_DIR)/file.o

  2. dependency should list ALL files that are needed to build the result , so make really rebuilds it if ANY of these files changed. dependency应列出生成result所需的所有文件, result ,如果这些文件中的任何一个发生更改, make真正重建它。 In your case, at least file.c is missing from the dependency list 在您的情况下,依赖项列表中至少缺少file.c

  3. In order to place files in a directory, you should make sure it exists. 为了将文件放置在目录中,应确保它存在。 you could do it like this: 您可以这样做:

     $(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. Your move_obj recipe, although not suitable in this case, would be a PHONY target, meaning it does not create a file. 您的move_obj配方虽然不适用于这种情况,但将成为PHONY目标,这意味着它不会创建文件。 If you need such rules, mark them accordingly by mentioning them as dependency of the special target .PHONY : 如果您需要这样的规则,请通过提及它们作为特殊目标.PHONY依赖项进行相应的.PHONY

     .PHONY: move_obj 

    The reason for this is that you could (by accident) have a file named move_obj in your working directory. 这样做的原因是,您可能(偶然)在工作目录中有一个名为move_obj的文件。 In that case, make would decide there's nothing to do for move_obj, and this is not what you want. 在这种情况下,make会决定对move_obj不执行任何操作,而这不是您想要的。 Marking it as phony tells make that this rule does not create its target and the recipe must be executed no matter what. 将其标记为phony可以表明该规则不会创建其目标,并且无论如何都必须执行配方。

All in all, your question comes down to misunderstanding a Makefile as kind of a script. 总而言之,您的问题归结为对Makefile的理解是一种脚本。 It is not. 它不是。 It's a declarative file that tells make what has to be done in order to build files (your evaluation block) and when this needs to be done (your dependency block). 它是一个说明性文件,告诉make必须执行什么操作才能构建文件(您的evaluation块)以及何时需要执行此操作(您的dependency块)。 It's better not to try to misuse a Makefile as a script. 最好不要尝试将Makefile用作脚本。

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

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