Понимание уровней зависимости make-файлов

#c #makefile #gnu-make

#c #makefile #gnu-make

Вопрос:

Предположим, что в проекте есть следующие файлы, где первые файлы зависят от файлов под его категорией в неупорядоченном списке:

  • main.c
    • global.h (содержит перечисления и макросы #define)
    • sdlevent.h (общий заголовочный файл)
      • sdlevent.c (содержит реализации sdlevent.h)
    • sdlshape.h (общий заголовочный файл)
      • sdlshape.c (содержит реализации sdlshape.h)

Теперь у меня есть следующий makefile:

 CC = gcc
CFLAGS = -g -w -std=c99
LIBS = -lSDL2 -lSDL2_image -lSDL2_ttf

SRCS = main.c sdlshape.c sdlevent.c
OBJS = $(SRCS:.c=.o)
EXE = play

all: $(EXE)

.c.o:
    $(CC) -c $(CFLAGS) $<

$(EXE): $(OBJS)
    $(CC) -o $(EXE) $(OBJS) $(LIBS)

$(OBJS): global.h sdlevent.h sdlshape.h

run : all
    ./$(EXE)

clean:
    rm -f *.o *~ $(EXE)
  

Цель $(EXE) зависит от цели .c.o . Обязательно ли мне определять цель $(EXE) после цели .c.o ?

Я так не думаю, потому что, хотя цель $(EXE) зависит от цели $(OBJS) , цель ($EXE) объявляется раньше $(OBJS) .

Комментарии:

1. Cmake имеет лучшие учебные пособия и является более общим инструментом, который генерирует make-файлы. Я настоятельно рекомендую проверить это.

2. @SimonHobbs, AFAIK, make — это самый общий инструмент для создания. Но если вы скажете, что Cmake — это, я проверю это. Спасибо за предложение.

3. @klaus я не уверен, но я думаю, что лучше всего удалить его.

Ответ №1:

Обязательно ли мне определять целевой $(EXE) после target .c.o?

Во-первых, .c.o это не цель, это правило суффикса.

Во-вторых, make не имеет значения, в какой последовательности записаны целевые объекты, поэтому ответ «нет». Читается весь makefile, и когда цель отсутствует, выполняется поиск правила для создания цели. Технически, make создает ориентированный ациклический граф (DAG) целевых объектов и зависимостей, прежде чем рассматривать возможность создания чего-либо. Ссылки на переменные заменяются при их использовании, а не при их чтении (исключение: := оператор присваивания GNU make).

Попробуйте поиграть с порядком целевых объектов. Вы даже можете переместить назначения переменных в самый низ.

Я уверен, что в GNU make есть несколько эзотерических уголков, где все работает немного по-другому, но в таком простом makefile, как ваш, не отклоняясь слишком далеко от makefile POSIX, вот как это работает.