Сначала прочитайте руководство по сборке GNU .Читать основную документацию лучше, чем угадывать.
Я ничего не вижу очевидно неправильно, но вы, конечно, можете немного упростить это.
GNU make позволяет вам использовать множество неявных правил , а не писать явное правило для каждой цели.Например, make
уже предоставляет неявное правило для компиляции любого файла *.c
в *.o
:
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
Автоматическая переменная $<
соответствует предварительному условию (правая часть :
), а переменная $@
соответствует цели.CC
, CFLAGS
и CPPFLAGS
- предопределенные имена переменных, используемые неявными правилами - вы просто устанавливаете для них значения, которые хотите использовать:
CC = gcc
CFLAGS = -std=c99 -pedantic -Wall -Werror
Таким образом, один способ упростить этоbe
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
соответственно.
Теперь, одна вещь, которую этот make-файл не делает , - это проверка зависимостей от файлов заголовка (.h).Вы можете переопределить неявное правило, добавив что-то вроде следующего:
%.o : %.c %.h
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
Это перестроит file .o, если либо file .c, либо file .h новее.Но иногда несколько файлов .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;
}
Вот make-файл:
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
Надеюсь, это поможет.Опять же, покопайтесь в руководстве по сборке, которое я связал выше, вы можете сделать с ним действительно классные вещи.