首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >命令中的命令?

命令中的命令?
EN

Stack Overflow用户
提问于 2015-07-06 12:28:03
回答 3查看 229关注 0票数 0

我有一个令人尴尬的简单的makefile问题,但我不能谷歌,因为缺乏知识-我不知道什么词我不知道。

基本上,我希望在当前目录中运行makefile,查看源文件的./SRC目录,当所有操作完成后,将对象文件移动到./OBJ目录中。

Makefile:

代码语言:javascript
复制
move_obj: 
    mv -f -t ./OBJ_DIR ./$(OBJ_FILES)

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

我想在编译源文件之后调用"move_obj“,但是我不知道是什么

代码语言:javascript
复制
result: dependency
    evaluation

实际上表示(以及我发现的所有makefile介绍指南)--“这就是makefile的样子,让您去吧”),我不知道为什么这不起作用。我想我需要一些评估命令或者需要定义一个函数或者.?

谢谢你提前提供帮助。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-07-06 12:54:14

您可以通过创建另一个rule (例如move )来做到这一点,如下所示

代码语言:javascript
复制
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目录并在那里使用它。

有点像

代码语言:javascript
复制
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。

代码语言:javascript
复制
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)

请参阅此answer以获得更好的理解

编辑

还可以将可执行文件输出到目录中,向Makefile添加以下更改。

确保bin目录是预先创建的,而不是由clean删除的。

代码语言:javascript
复制
# 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)
票数 2
EN

Stack Overflow用户

发布于 2015-07-06 12:45:58

如果您想一个接一个地构建一个目标(move_obj)(file.o),那么将move_obj添加到file.o的依赖项列表中,以便执行move_obj下的命令。

所以你的Makefile应该是:

代码语言:javascript
复制
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在注释部分中提到的,您可以在所需的目录中构建对象文件,而不是编译然后移动。

代码语言:javascript
复制
file.o: other_file.h
    $(CC) $(CFLAGS) $(CPPFLAGS) -c file.c -o ./$(OBJ_FILES)/$@
票数 1
EN

Stack Overflow用户

发布于 2015-07-06 13:11:13

这在各种方面都有缺陷。

  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) $(CFLAGS)$ -c file.c -o $(OBJ_DIR)/file.o
  4. 您的move_obj菜谱虽然在本例中不合适,但它将是一个PHONY目标,这意味着它不会创建一个文件。如果需要这样的规则,请相应地将它们标记为特殊目标.PHONY的依赖关系: .PHONY: move_obj 原因是您可以(偶然地)在您的工作目录中有一个名为move_obj的文件。在这种情况下,make会决定move_obj没有什么可做的,这不是您想要的。把它标记为假的告诉make,这个规则不会创建它的目标,无论如何都必须执行它的配方。

总之,你的问题归结为把Makefile误解为一种脚本。事实并非如此。它是一个声明性文件,它告诉make要构建文件( evaluation块)必须做什么,以及什么时候需要完成( dependency块)。最好不要试图误用Makefile作为脚本。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31245851

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档