GNU Make забывает предпосылки? - PullRequest
0 голосов
/ 06 июля 2010

Это немного сложно, поэтому я загрузил пример здесь .

Как это проверить:

  • Загрузите архив и распакуйте его
  • cd make_problem / make
  • make aclean (забыл удалить архив из архива;))
  • make alib (заново создаст простой и глупый архив, который вы только что удалили)
  • . / Weird.sh

Что делает weird.sh, так это просто касается исходного файла, переделывает, касается другого исходного файла, переделывает несколько раз.

Вот как выглядит вывод в моей системе Linux с использованием GNU Make 3.81:

$ ./weird.sh
####  1  ####
gcc -c -g -Wall -Wextra  -o ../swu/1/src/foo1.o ../swu/1/src/foo1.c

ar cr ../make/libmine.a ../swu/1/src/foo1.o
====  1  ====
gcc -c -g -Wall -Wextra  -o ../swu/1/src/bar1.o ../swu/1/src/bar1.c

ar cr ../make/libmine.a ../swu/1/src/bar1.o
####  2  ####
gcc -c -g -Wall -Wextra  -o ../swu/1/src/foo2.o ../swu/1/src/foo2.c

====  2  ====
gcc -c -g -Wall -Wextra  -o ../swu/1/src/bar2.o ../swu/1/src/bar2.c

####  3  ####
gcc -c -g -Wall -Wextra  -o ../swu/1/src/foo3.o ../swu/1/src/foo3.c

====  3  ====
gcc -c -g -Wall -Wextra  -o ../swu/1/src/bar3.o ../swu/1/src/bar3.c

####  4  ####
gcc -c -g -Wall -Wextra  -o ../swu/1/src/foo4.o ../swu/1/src/foo4.c

====  4  ====
gcc -c -g -Wall -Wextra  -o ../swu/1/src/bar4.o ../swu/1/src/bar4.c

####  5  ####
gcc -c -g -Wall -Wextra  -o ../swu/1/src/foo5.o ../swu/1/src/foo5.c

====  5  ====
gcc -c -g -Wall -Wextra  -o ../swu/1/src/bar5.o ../swu/1/src/bar5.c

####  6  ####
gcc -c -g -Wall -Wextra  -o ../swu/1/src/foo6.o ../swu/1/src/foo6.c

====  6  ====
gcc -c -g -Wall -Wextra  -o ../swu/1/src/bar6.o ../swu/1/src/bar6.c

####  7  ####
gcc -c -g -Wall -Wextra  -o ../swu/1/src/foo7.o ../swu/1/src/foo7.c

====  7  ====
gcc -c -g -Wall -Wextra  -o ../swu/1/src/bar7.o ../swu/1/src/bar7.c

ar cr ../make/libmine.a ../swu/1/src/bar7.o
####  8  ####
gcc -c -g -Wall -Wextra  -o ../swu/1/src/foo8.o ../swu/1/src/foo8.c

====  8  ====
gcc -c -g -Wall -Wextra  -o ../swu/1/src/bar8.o ../swu/1/src/bar8.c

$

Теперь я ожидал, что архив будет перестраиваться при каждом прикосновении к источнику, но этого явно не произошло.

Может кто-нибудь объяснить это? И объясните, как сделать так, чтобы он всегда работал как положено?

1 Ответ

2 голосов
/ 12 июля 2010

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

В частности, weird.sh will:

  1. touch foo1.c
  2. run make, который
    1. восстанавливает foo1.o и
    2. восстанавливает libmine.a
  3. touch bar1.c
  4. run make, который
    1. восстанавливает bar1.o
    2. возможно (см. Ниже) восстанавливает libmine.a

Если время между шагом 2.2 и шагом 4.2 меньше, чем разрешение метки времени вашей файловой системы, то make видит, что libmine.a уже имеет такую ​​же метку времени как bar1.o, и поэтому не перестраивает его.

Разрешение временной метки для файловой системы Linux ext3 составляет 1 секунду.Это объяснение от сопровождающего make описывает проблему более подробно, а также упоминает, что Solaris имеет лучшее разрешение метки времени, что, вероятно, объясняет, почему ваш пример работает там, как ожидалось.

Если это такпроблема для вас в реальном приложении, вы можете попробовать файловую систему ext4, которая имеет временные метки с наносекундным разрешением.В противном случае просто вставьте sleep 1 после каждой команды make в weird.sh, и проблема исчезнет: -)

...