В чем разница между удалением и изменением времени модификации файла (touch) в контексте команды `make`?

Здравствуйте! Прохожу курс “от 0 до Linux админа” вот здесь https://yodo.im/courses/linux/?v=1d20b5ff1ee9 и столкнулся с проблемой, касающейся разницы между удалением и изменением времени (touch) файла в контексте команды make. Вот код:

blah: blah.o
    cc blah.o -o blah # Запускается третьим

blah.o: blah.c
    cc -c blah.c -o blah.o # Запускается вторым

blah.c:
    echo "int main() { return 0; }" > blah.c # Запускается первым

Когда я запускаю команду make, получаю ожидаемый вывод. Если же я выполняю touch для файла blah.c, вывод будет cc -c blah.c -o blah.o cc blah.o -o blah, но при удалении файла blah.c он создаётся заново, и вывод будет echo "int main() {return 0; }" > blah.c cc -c blah.c -o blah.o cc blah.o -o blah.

Не могу понять, как “blah” узнал, что blah.c недоступен. Он просто проверил blah.o, чей временной штамп не изменился. Получается, что blah.o проверяет наличие blah.c на обновления, когда его проверяет “blah”? Почему выводы разные? Неужели в случае с touch файл blah.c не был удалён, и blah.o поэтому просто обновил свой временной штамп? Что на самом деле происходит?

Здравствуйте!

Отличный вопрос! Давайте попробуем разобраться в том, что происходит в вашем сценарии с использованием команды make, командой touch и удалением файла.

Работа make

Когда вы запускаете команду make, она проверяет зависимости, указанные в вашем Makefile, и на основе временных меток файлов определяет, какие цели нужно пересобрать.

  1. Первый запуск make:

    • blah.c не существует, и команда make видит, что нужно создать этот файл. Она запускает команду, создающую blah.c, и затем переходит к сборке blah.o, а потом и blah.
  2. Использование touch:

    • Когда вы выполняете touch blah.c, вы не изменяете содержимое файла, но обновляете его временной штамп. Это означает, что make видит, что blah.c “существует” и его временной штамп — свежий, но это не приводит к пересборке blah.o, если blah.o уже скомпилирован и временной штамп blah.o не изменился.
    • Таким образом, при следующем запуске make, make решает, что у него уже есть актуальная версия blah.o, и просто компилирует blah.
  3. Удаление файла:

    • Когда вы удаляете blah.c, make обнаруживает, что файл отсутствует. При этом blah.o уже был скомпилирован, но так как blah.c недоступен, make запускает команду для его создания заново.
    • После этого он снова компилирует blah.o и затем собирает blah, в результате чего вы получаете различные выводы.

Объяснение различий

  • В случае с touch файл blah.c остается на месте, только его временной штамп обновляется. Это говорит make, что ничего менять в blah.o не надо, так как зависимость выполнена.
  • При удалении же blah.c, make понимает, что зависимости нарушены, поэтому он должен заново создать blah.c и скомпилировать blah.o.

Вывод

Таким образом, временные метки здесь играют критическую роль. make анализирует эти временные метки и принимает решения об необходимости пересборки на их основе. Надеюсь, это поможет прояснить ситуацию! Если у вас есть еще вопросы, не стесняйтесь задавать! . Я ответил на ваш вопрос?

Спасибо за ответ! У меня все получилось.

Отлично, рад слышать, что все получилось! Если будут еще вопросы или понадобится помощь, не стесняйся обращаться. :blush: . Я ответил на ваш вопрос?