Почему make не перестраивается при изменении исходных файлов? - PullRequest
0 голосов
/ 18 марта 2019

В настоящее время я пытаюсь выполнить задачу 4 (speller) из курса CS50. Это первый набор проблем, когда у нас есть несколько файлов заголовков и несколько исходных файлов, поэтому они дали нам Makefile для использования, чтобы скомпилировать каждый файл .c в .o, а затем связать файлы .o для формирования скомпилированного двоичного файла.

Это make-файл

speller:
    clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o speller.o speller.c
    clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o dictionary.o dictionary.c
    clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -o speller speller.o dictionary.o

Вывод ls:

dictionaries  dictionary.h  keys      speller    speller.o dictionary.c  dictionary.o  Makefile  speller.c  texts

Когда я запускаю make впервые, он без проблем компилирует speller. Тем не менее, когда я делаю изменения в dictionary.c и сохраняю его (в частности, я специально облажал все свои вызовы printf () для printasdasdsa (), да, вы получаете его), и я запускаю make, он продолжает говорить make: 'speller' is up to date, и просто отказывается перестраивать, хотя я внес изменения в источник dictionary.c.

Есть идеи, что не так с тем, как я строю спеллер? Что-то не так с моим make-файлом?

Я знаю, что есть способ принудительно перестроить make, передав флаг "-B", но принято ли всегда делать это таким образом, когда вы вносите изменения в свой код?

Это задание: https://docs.cs50.net/2019/x/psets/4/speller/hashtable/speller.html

Ответы [ 3 ]

1 голос
/ 19 марта 2019

@ HardcoreHenry очень хорошо объясняет поведение make в своем ответе (не принимайте это за это). Однако я хочу отметить, что make имеет достаточное количество встроенных умений для создания программного обеспечения, в той степени, в которой он может делать относительно простые сборки без какого-либо Makefile. Более того, когда вы пишете Makefile, обычно считается хорошим стилем минимизировать повторения.

Таким образом, я бы предложил это как еще лучшую альтернативу:

CC = clang
CFLAGS = -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 \
  -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare       \
  -Wno-unused-parameter -Wno-unused-variable -Wshadow

speller: speller.o dictionary.o
    $(CC) -o $@ $(CFLAGS) speller.o dictionary.o

Это опирается на make, зная, как создавать объектные файлы из исходных файлов C (что он делает), и используя компилятор C и флаги, определенные переменными CC и CFLAGS, когда это происходит (что он делает). будут). Он также использует специальную переменную $@, которая в рецепте правила расширяется до имени цели правила. Некоторые версии make предлагают еще больше возможностей высушить это.

Помимо прочего, обратите внимание, как флаги компилятора и сборки указываются по одному разу и в верхней части. Теперь, если вы когда-нибудь захотите их изменить, вы можете сделать это в одном легко доступном месте.

1 голос
/ 18 марта 2019

Make восстанавливает только цель, если цель не существует или цель старше одной из ее зависимостей. В вашем случае у вас есть цель speller, без зависимостей. Когда вы запускаете его в первый раз, делаете проверки и не находите его, поэтому он его создает. В следующий раз, когда вы строите, он проверяет, существует ли файл, и, поскольку он не имеет никаких зависимостей, он не перестраивается. Вы хотели бы сделать что-то вроде:

speller:  speller.c dictionary.c
    clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o speller.o speller.c
    clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o dictionary.o dictionary.c
    clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -o speller speller.o dictionary.o

Или, еще лучше:

speller: speller.o dictionary.o
    clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -o speller speller.o dictionary.o

speller.o: speller.c
    clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o speller.o speller.c

dictionary.o: dictionary.c
    clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o dictionary.o dictionary.c

Что не будет перестраивать файлы .o, если только файлы .c не изменены, и не будет перестраивать приложение, если один из файлов .o не будет перестроен. Обратите внимание, что ни из этих двух не обрабатывают файлы заголовков. Если ваши файлы .c содержат какие-либо локальные заголовки, их также необходимо добавить в зависимости.

0 голосов
/ 19 марта 2019

Вам нужно добавить зависимости. При использовании GNU make вы можете пропустить шаг .o для небольших проектов и скомпилировать программу целиком

speller:  speller.c dictionary.c
         ${CLANG} ${CFLAGS} ${LDFLAGS} $(filter %.c,$^) -o $@ ${LIBS}
...