我被要求做一个makefile,我已经这样做了:
# La siguiente no es necesariamente requerida, se agrega para
# mostrar como funciona.
.SUFFIXES: .o .c
.c.o:
$(CC) -c $(CFLAGS) $<
# Macros
CC = g++
CFLAGS = -Wall -Wextra -Werror -pedantic
SRC = main.c metbasicos.c metbasicos.h metintermedios.c metintermedios.h metavanzados.c metavanzados.h
OBJ = main.c metbasicos.c metintermedios.c metavanzados.c
# Reglas explicitas
all: $(OBJ)
$(CC) $(CFLAGS) -o p1 $(OBJ)
clean:
$(RM) $(OBJ) main
# Reglas implicitas
metbasicos.o: metbasicos.c metbasicos.h
metintermedios.o: metintermedios.c metintermedios.h
metavanzados.o: metavanzados.c metavanzados.h
main.o: main.c metbasicos.h metintermedios.h metavanzados.h
这是对的吗?
要编译,我通常使用以下命令:
g++ -Wall -Wextra -Werror -pedantic main.c metbasicos.c metintermedios.c metavanzados.c -o p1.exe
如果我用以下方法进行一些测试:
make
./p1 < input.txt
工作正常,但我不确定它是否是正确的实现。
有人可以告诉我,我是否犯了一些严重的错误?
非常感谢。
答案 0 :(得分:3)
这里没有任何严重错误,但有一些奇怪的事情。正如Ignacio指出的那样,如果你不愿意,你根本不需要重新定义编译规则。但你可能做到这一点的原因是你混淆了C和C ++。
您正在构建.c
文件,这些文件是按照惯例的C代码,g++
是一个C ++编译器,这是奇怪的。如果您真的在构建C代码,则应使用gcc
进行编译。如果您真的正在构建C ++代码,则应将文件重命名为.cpp
或.cc
或类似名称。此外,C ++编译器的GNU make变量是CXX
,而不是CC
,而标志的变量是CXXFLAGS
而不是CFLAGS
。
此外,您的all
目标应取决于p1
,p1
目标应包含该链接:
.PHONY: all
all: p1
p1: $(OBJ)
$(CC) $(CFLAGS) -o p1 $(OBJ)
每当您运行p1
时,即使未进行任何更改,make
也会重新关联。
您还可以添加其他更高级的内容,例如自动构建头文件先决条件等等。
答案 1 :(得分:1)
$(CFLAGS)
是编译标志:在将.c
源文件编译为.o
目标文件时使用它们。
在执行$(CFLAGS)
时使用$(CC) -o $(OBJ)
并不常见,但效果很好。一种正确的方法是使用$(LDFLAGS)
标记进行链接过程,将所有.o
与您正在使用的可能库一起放入二进制可执行文件中。
通常$(CFLAGS)包含编译选项,例如您使用的编译选项,$(LDFLAGS)包含链接选项,例如-L. -lpersonal
,用于在与makefile相同的目录中加载名为libpersonal.a
的文件
此外,我建议您在+=
声明中使用CFLAGS
来保留现有的CFLAGS(如果已有的话)。
如果您不想为每个文件设置规则,那么.c.o
规则很有用,您在底部执行了哪些操作。最佳做法是为每个文件定义自定义规则,将源文件包含的头文件添加为该规则的依赖关系。这样,makefile将只管理重新编译需要的文件,因为源或更改了包含的标头。当然,当您更改每个源中包含的头文件时,需要对源文件和进行全面分析。