我正在研究一个项目,因此需要为其创建一个makefile
。
以下是我需要遵循的文件和约定:
makefile中必须具有以下标签:
全部:program5
program5: program5.o stack.o queue.o vector.o list.o profile.o
gcc -g program5.o stack.o queue.o vector.o list.o profile.o -o program5
program5.o: program5.c stack.h queue.h vector.h list.h profile.h
gcc -g -c program5.c -o program5.o
stack.o: stack.c stack.h
gcc -g -c stack.c -o stack.o
queue.o: queue.c queue.h
gcc -g -c queue.c -o queue.o
vector.o: vector.c vector.h
gcc -g -c vector.c -o vector.o
list.o: list.c list.h
gcc -g -c list.c -o list.o
profile.o: profile.c profile.h
gcc -g -c profile.c -o profile.o
run: all
./program5
memcheck: all
valgrind -v ./program5
clean:
rm -f *.o program5
这是我在makefile
文件中需要进行以下导入的program5.c
的外观。我想知道我在makefile
中写的内容是否正确?
例如,program5
和program5.o
部分是正确的,还是我应该将它们拆散更多或其他?
#include "stack.h"
#include "stack.h"
#include "queue.h"
#include "queue.h"
#include "vector.h"
#include "vector.h"
#include "list.h"
#include "list.h"
#include "profile.h"
#include "profile.h"
答案 0 :(得分:2)
首先,请阅读GNU make manual。阅读主要文档胜于猜测。
我没有发现任何错误,但可以肯定地将其简化了很多。
GNU make允许您使用各种隐式规则,而不是为每个目标编写一个显式规则。例如,make
已经提供了一个隐式规则,可将任何*.c
文件编译为*.o
:
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
自动变量$<
对应于先决条件(:
的右侧),变量$@
对应于目标。 CC
,CFLAGS
和CPPFLAGS
是隐式规则使用的预定义变量名-您只需将它们设置为要使用的值即可:
CC = gcc
CFLAGS = -std=c99 -pedantic -Wall -Werror
因此,简化此操作的一种方法是
CC = gcc
CFLAGS = -std=c99 -pedantic -Wall -Werror
SRCS = program5.c stack.c queue.c vector.c list.c profile.c
OBJS = $(SRCS:.c=.o)
TARGET=program5
##
## rebuild the target if any of the object files are newer
##
$(TARGET) : $(OBJS)
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(OBJS) -o $@
all : $(TARGET)
run : all
./$(TARGET)
memcheck: all
valgrind -v $(TARGET)
clean:
rm -rf $(TARGET) $(OBJS)
请注意,无需为单独的.o
文件编写任何规则-再次,GNU Make已经提供了该规则。您只需要适当地设置CC
,CFLAGS
和CPPFLAGS
。
现在,此makefile做不做的一件事是检查对头文件(.h)的依赖性。您可以通过添加如下内容来覆盖隐式规则:
%.o : %.c %.h
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
如果 file .c或 file .h较新,则会重建 file .o。但是有时多个.c文件包含相同的.h文件,因此,如果单个标头更改,则可能需要触发多个构建。
gcc可以选择生成Makefile规则列表。例如,如果program5.c
包含上述所有标头,则gcc -MM program5.c
将生成输出
program5.o : program5.c list.h profile.h queue.h stack.h vector.h
您可以将此输出写入文件,然后将该文件包含在主Makefile中。这是上面链接的GNU make手册中的一个示例:
##
## For each source file, create a .d file that explicitly lists the header
## dependencies.
##
%.d : %.c
@set -e; rm -f $@; \
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -rf $@.$$$$
然后在您添加clean
目标之后
include $(SRCS:.c=.d)
包括生成的.d文件。
编辑
这是一个可行的示例(主要是为了确保我没有对你说谎)。我生成了一组.c和.h文件:
[fbgo448@n9dvap997]~/prototypes/make: ls
total 56
drwxrwxr-x 2 fbgo448 users 4096 2018-12-07 09:28 .
drwxrwxr-x 163 fbgo448 users 16384 2018-12-07 09:11 ..
-rw-rw-r-- 1 fbgo448 users 52 2018-12-07 09:25 data.h
-rw-rw-r-- 1 fbgo448 users 83 2018-12-07 09:12 list.c
-rw-rw-r-- 1 fbgo448 users 58 2018-12-07 09:12 list.h
-rw-rw-r-- 1 fbgo448 users 512 2018-12-07 09:28 Makefile
-rw-rw-r-- 1 fbgo448 users 93 2018-12-07 09:14 profile.c
-rw-rw-r-- 1 fbgo448 users 67 2018-12-07 09:13 profile.h
-rw-rw-r-- 1 fbgo448 users 264 2018-12-07 09:24 program5.c
-rw-rw-r-- 1 fbgo448 users 86 2018-12-07 09:14 queue.c
-rw-rw-r-- 1 fbgo448 users 62 2018-12-07 09:14 queue.h
-rw-rw-r-- 1 fbgo448 users 87 2018-12-07 09:15 stack.c
-rw-rw-r-- 1 fbgo448 users 62 2018-12-07 09:15 stack.h
-rw-rw-r-- 1 fbgo448 users 89 2018-12-07 09:16 vector.c
-rw-rw-r-- 1 fbgo448 users 65 2018-12-07 09:16 vector.h
这些非常简单-它们只定义一个打印模块名称的函数,如下所示:
[fbgo448@n9dvap997]~/prototypes/make: more stack.*
::::::::::::::
stack.c
::::::::::::::
#include <stdio.h>
#include "stack.h"
void stack( void )
{
printf( "stack\n" );
}
::::::::::::::
stack.h
::::::::::::::
#ifndef STACK_H
#define STACK_H
void stack( void );
#endif
program5
除外,它会呼叫其他人:
[fbgo448@n9dvap997]~/prototypes/make: more program5.c
#include <stdio.h>
#include "data.h"
#include "list.h"
#include "profile.h"
#include "queue.h"
#include "stack.h"
#include "vector.h"
int main( void )
{
printf( "g_data = %d\n", g_data ); // defined in data.h
list();
profile();
queue();
stack();
vector();
return 0;
}
这是makefile:
CC=gcc
CFLAGS= -std=c99 -pedantic -Wall -Werror
CPPFLAGS=
SRCS=program5.c list.c profile.c queue.c stack.c vector.c
##
## The following lines are examples of pattern substitions - the SRCS
## variable will be expanded, and each _file_.c will be replaced with
## a _file_.o for OBJS and _file_.d for DEPS.
##
OBJS=$(SRCS:.c=.o)
DEPS=$(SRCS:.c=.d)
TARGET=program5
##
## Build the dependency files
##
%.d : %.c
set -e; rm -rf $@; \
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : , g' < $@.$$$$ > $@; \
rm -rf $@.$$$$
$(TARGET) : $(OBJS)
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(OBJS) -o $@
all: $(TARGET)
run: all
./$(TARGET)
memcheck: all
valgrind -v $(TARGET)
clean:
rm -rf $(TARGET) $(OBJS) $(DEPS)
##
## The '-' in front of the include directive will suppress a warning
## if any of the .d files cannot be found. This will be the case the
## first time you run the makefile, or after running a 'make clean'.
##
-include $(DEPS)
这是运行make run
的结果:
[fbgo448@n9dvap997]~/prototypes/make: make run
set -e; rm -rf vector.d; \
gcc -MM vector.c > vector.d.$$; \
sed 's,\(vector\)\.o[ :]*,\1.o vector.d : , g' < vector.d.$$ > vector.d; \
rm -rf vector.d.$$
set -e; rm -rf stack.d; \
gcc -MM stack.c > stack.d.$$; \
sed 's,\(stack\)\.o[ :]*,\1.o stack.d : , g' < stack.d.$$ > stack.d; \
rm -rf stack.d.$$
set -e; rm -rf queue.d; \
gcc -MM queue.c > queue.d.$$; \
sed 's,\(queue\)\.o[ :]*,\1.o queue.d : , g' < queue.d.$$ > queue.d; \
rm -rf queue.d.$$
set -e; rm -rf profile.d; \
gcc -MM profile.c > profile.d.$$; \
sed 's,\(profile\)\.o[ :]*,\1.o profile.d : , g' < profile.d.$$ > profile.d; \
rm -rf profile.d.$$
set -e; rm -rf list.d; \
gcc -MM list.c > list.d.$$; \
sed 's,\(list\)\.o[ :]*,\1.o list.d : , g' < list.d.$$ > list.d; \
rm -rf list.d.$$
set -e; rm -rf program5.d; \
gcc -MM program5.c > program5.d.$$; \
sed 's,\(program5\)\.o[ :]*,\1.o program5.d : , g' < program5.d.$$ > program5.d; \
rm -rf program5.d.$$
gcc -std=c99 -pedantic -Wall -Werror -c -o program5.o program5.c
gcc -std=c99 -pedantic -Wall -Werror -c -o list.o list.c
gcc -std=c99 -pedantic -Wall -Werror -c -o profile.o profile.c
gcc -std=c99 -pedantic -Wall -Werror -c -o queue.o queue.c
gcc -std=c99 -pedantic -Wall -Werror -c -o stack.o stack.c
gcc -std=c99 -pedantic -Wall -Werror -c -o vector.o vector.c
gcc -std=c99 -pedantic -Wall -Werror program5.o list.o profile.o queue.o stack.o vector.o -o program5
./program5
g_data = 0
list
profile
queue
stack
vector
下面是生成的.d和.o文件的列表:
[fbgo448@n9dvap997]~/prototypes/make: ls
total 96
drwxrwxr-x 2 fbgo448 users 4096 2018-12-07 09:50 .
drwxrwxr-x 163 fbgo448 users 16384 2018-12-07 09:11 ..
-rw-rw-r-- 1 fbgo448 users 52 2018-12-07 09:25 data.h
-rw-rw-r-- 1 fbgo448 users 83 2018-12-07 09:12 list.c
-rw-rw-r-- 1 fbgo448 users 30 2018-12-07 09:50 list.d
-rw-rw-r-- 1 fbgo448 users 58 2018-12-07 09:12 list.h
-rw-rw-r-- 1 fbgo448 users 1480 2018-12-07 09:50 list.o
-rw-rw-r-- 1 fbgo448 users 974 2018-12-07 09:48 Makefile
-rw-rw-r-- 1 fbgo448 users 93 2018-12-07 09:14 profile.c
-rw-rw-r-- 1 fbgo448 users 42 2018-12-07 09:50 profile.d
-rw-rw-r-- 1 fbgo448 users 67 2018-12-07 09:13 profile.h
-rw-rw-r-- 1 fbgo448 users 1480 2018-12-07 09:50 profile.o
-rwxrwxr-x 1 fbgo448 users 10070 2018-12-07 09:50 program5
-rw-rw-r-- 1 fbgo448 users 264 2018-12-07 09:24 program5.c
-rw-rw-r-- 1 fbgo448 users 84 2018-12-07 09:50 program5.d
-rw-rw-r-- 1 fbgo448 users 1864 2018-12-07 09:50 program5.o
-rw-rw-r-- 1 fbgo448 users 86 2018-12-07 09:14 queue.c
-rw-rw-r-- 1 fbgo448 users 34 2018-12-07 09:50 queue.d
-rw-rw-r-- 1 fbgo448 users 62 2018-12-07 09:14 queue.h
-rw-rw-r-- 1 fbgo448 users 1480 2018-12-07 09:50 queue.o
-rw-rw-r-- 1 fbgo448 users 87 2018-12-07 09:15 stack.c
-rw-rw-r-- 1 fbgo448 users 34 2018-12-07 09:50 stack.d
-rw-rw-r-- 1 fbgo448 users 62 2018-12-07 09:15 stack.h
-rw-rw-r-- 1 fbgo448 users 1480 2018-12-07 09:50 stack.o
-rw-rw-r-- 1 fbgo448 users 89 2018-12-07 09:16 vector.c
-rw-rw-r-- 1 fbgo448 users 38 2018-12-07 09:50 vector.d
-rw-rw-r-- 1 fbgo448 users 65 2018-12-07 09:16 vector.h
-rw-rw-r-- 1 fbgo448 users 1480 2018-12-07 09:50 vector.o
make clean
将删除所有生成的文件:
[fbgo448@n9dvap997]~/prototypes/make: make clean
rm -rf program5 program5.o list.o profile.o queue.o stack.o vector.o program5.d list.d profile.d queue.d stack.d vector.d
[fbgo448@n9dvap997]~/prototypes/make: ls
total 56
drwxrwxr-x 2 fbgo448 users 4096 2018-12-07 09:51 .
drwxrwxr-x 163 fbgo448 users 16384 2018-12-07 09:11 ..
-rw-rw-r-- 1 fbgo448 users 52 2018-12-07 09:25 data.h
-rw-rw-r-- 1 fbgo448 users 83 2018-12-07 09:12 list.c
-rw-rw-r-- 1 fbgo448 users 58 2018-12-07 09:12 list.h
-rw-rw-r-- 1 fbgo448 users 974 2018-12-07 09:48 Makefile
-rw-rw-r-- 1 fbgo448 users 93 2018-12-07 09:14 profile.c
-rw-rw-r-- 1 fbgo448 users 67 2018-12-07 09:13 profile.h
-rw-rw-r-- 1 fbgo448 users 264 2018-12-07 09:24 program5.c
-rw-rw-r-- 1 fbgo448 users 86 2018-12-07 09:14 queue.c
-rw-rw-r-- 1 fbgo448 users 62 2018-12-07 09:14 queue.h
-rw-rw-r-- 1 fbgo448 users 87 2018-12-07 09:15 stack.c
-rw-rw-r-- 1 fbgo448 users 62 2018-12-07 09:15 stack.h
-rw-rw-r-- 1 fbgo448 users 89 2018-12-07 09:16 vector.c
-rw-rw-r-- 1 fbgo448 users 65 2018-12-07 09:16 vector.h
感谢自动生成的依存关系,如果我更新data.h
,应该会触发program5.c
的构建:
[fbgo448@n9dvap997]~/prototypes/make: touch data.h
[fbgo448@n9dvap997]~/prototypes/make: make
set -e; rm -rf program5.d; \
gcc -MM program5.c > program5.d.$$; \
sed 's,\(program5\)\.o[ :]*,\1.o program5.d : , g' < program5.d.$$ > program5.d; \
rm -rf program5.d.$$
gcc -std=c99 -pedantic -Wall -Werror -c -o program5.o program5.c
gcc -std=c99 -pedantic -Wall -Werror program5.o list.o profile.o queue.o stack.o vector.o -o program5
类似地,如果我更新stack.h
,则应该触发stack.c
和program5.c
的重建:
[fbgo448@n9dvap997]~/prototypes/make: touch stack.h
[fbgo448@n9dvap997]~/prototypes/make: make
set -e; rm -rf stack.d; \
gcc -MM stack.c > stack.d.$$; \
sed 's,\(stack\)\.o[ :]*,\1.o stack.d : , g' < stack.d.$$ > stack.d; \
rm -rf stack.d.$$
set -e; rm -rf program5.d; \
gcc -MM program5.c > program5.d.$$; \
sed 's,\(program5\)\.o[ :]*,\1.o program5.d : , g' < program5.d.$$ > program5.d; \
rm -rf program5.d.$$
gcc -std=c99 -pedantic -Wall -Werror -c -o program5.o program5.c
gcc -std=c99 -pedantic -Wall -Werror -c -o stack.o stack.c
gcc -std=c99 -pedantic -Wall -Werror program5.o list.o profile.o queue.o stack.o vector.o -o program5
希望这会有所帮助。再次,深入研究我上面链接的制作手册,您可以使用它做一些非常酷的事情。
答案 1 :(得分:1)
我不知道您的makefile
是否有效,但是请注意,您并不需要所有的-o
gcc -g -c vector.c -o vector.o
应该是
gcc -g -c vector.c
无论如何,您可以使用一些指令来改进它:
CC = gcc
CFLAGS = -g
OBJECTS = program5.o stack.o queue.o vector.o list.o profile.o
all: program5
program5: $(OBJECTS)
$(CC) $(OBJECTS) -o program5
program5.o: program5.c stack.h queue.h vector.h list.h profile.h
$(CC) $(CFLAGS) -c program5.c
stack.o: stack.c stack.h
$(CC) $(CFLAGS) -c stack.c
queue.o: queue.c queue.h
$(CC) $(CFLAGS) -c queue.c
vector.o: vector.c vector.h
$(CC) $(CFLAGS) -c vector.c
list.o: list.c list.h
$(CC) $(CFLAGS) -c list.c
profile.o: profile.c profile.h
$(CC) $(CFLAGS) -c profile.c
run: all
./program5
memcheck: all
valgrind -v ./program5
clean:
rm -f *.o program5
编译警告信息是一个好主意:
CFLAGS = -pedantic -Wall -Wextra -W -g
代替
CFLAGS = -g