Подтвердить что ты не робот

Что такое правила двойной толстой кишки в Makefile?

Раздел 4.13 руководства GNU Make описывает так называемые правила двойной толстой кишки:

Правила двойной толстой кишки - это правила, написанные с помощью ":: вместо": после имен целей. Они обрабатываются иначе, чем обычные правила, когда одна и та же цель отображается более чем в одном правиле.

Когда цель появляется в нескольких правилах, все правила должны быть одного типа: все обычные или все двойные двоеточие. Если они представляют собой двойную кишку, каждая из них не зависит от других. Команды каждой команды двойного двоеточия выполняются, если цель старше любых предварительных условий этого правила. Если для этого правила нет предпосылок, его команды всегда выполняются (даже если цель уже существует). Это может привести к выполнению ни одного, ни одного или всех правил с двумя двоеточиями.

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

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

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

Каждое правило двойной толстой кишки должно указывать команды; если это не так, будет использоваться неявное правило, если оно применяется. См. Раздел Использование неявных правил.

Я как бы понимаю смысл каждого предложения этого раздела в отдельности, но мне все еще не ясно, для чего предназначены правила двойной толстой кишки. Что касается редкостей, я еще не видел ни одного проекта с открытым исходным кодом, чей Makefile не начинался с

all::

Следовательно: Какова предполагаемая цель правил с двумя двоеточиями в Make файлах?

4b9b3361

Ответ 1

Здесь есть отличный ответ:

http://owen.sj.ca.us/~rk/howto/slides/make/slides/makecolon.html

Оуэн объясняет, как:: правила обрабатываются независимо, позволяя каждому правилу быть более простым. В его примере одно правило:

libxxx.a : sub1.o sub2.o
    ar rv libxxx.a sub1.o
    ar rv libxxx.a sub2.o

можно заменить двумя более простыми правилами:

libxxx.a :: sub1.o
    ar rv libxxx.a sub1.o

libxxx.a :: sub2.o
    ar rv libxxx.a sub2.o

Оуэн указывает, что утилиты, такие как AutoMake, легче выплескивают множество простых правил, чем несколько сложных.

Ответ 2

Они удобны для нерекурсивных make файлов и целей, таких как clean. То есть, отдельный файл .mk может добавлять свои собственные команды к цели clean, уже определенной в другом месте.

Документация дает ответ:

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

Ответ 3

Как говорит документация, правила двойной толстой кишки редко очень полезны. Они - хороший, маленький способ не называть отдельные цели сложной фальшивой цели (как и все::), но в действительности не нужны в этой роли. Я могу создать только один надуманный пример, где они необходимы:

Предположим, что у вас есть файл журнала L, который объединен с несколькими другими лог файлами L1, L2,... Вы формулируете несколько правил с двумя двоеточиями, например:

L :: L1
     cat $< >> [email protected] && rm $<

L :: L2
     cat $< >> [email protected] && rm $<

В настоящее время в GNU make вы, конечно, используете $^ для такого рода магии, но он указан как вдохновленная функция на вкладке функций GNU.

Ответ 4

Есть три ситуации, когда полезно использовать двойной двоеточие:

  • Альтернатива между правилами компиляции, на основе которых предварительное условие более новое, чем целевое. Следующий пример основан на "Пример 19-3. Правила двойной толстой кишки" из http://books.gigatux.nl/mirror/cinanutshell/0596006977/cinanut-CHP-19-SECT-3.html

Пример файла .c:

[email protected]:~/test/circle$ cat circle.c 
#include <stdio.h>

int main (void)
{
  printf("Example.\n");
  return 0;
}

Используемый файл Makefile:

[email protected]:~/test/circle$ cat Makefile 
# A makefile for "circle" to demonstrate double-colon rules.

CC = gcc
RM = rm -f
CFLAGS = -Wall -std=c99
DBGFLAGS = -ggdb -pg
DEBUGFILE = ./debug
SRC = circle.c

circle :: $(SRC)
        $(CC) $(CFLAGS) -o [email protected] -lm $^

circle :: $(DEBUGFILE)
        $(CC) $(CFLAGS) $(DBGFLAGS) -o [email protected] -lm $(SRC)

.PHONY : clean

clean  :
        $(RM) circle

Результат:

[email protected]:~/test/circle$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c
make: *** No rule to make target 'debug', needed by 'circle'.  Stop.
[email protected]:~/test/circle$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c
gcc -Wall -std=c99 -ggdb -pg -o circle -lm circle.c
[email protected]:~/test/circle$ vim circle.c 
[email protected]:~/test/circle$ make circle
gcc -Wall -std=c99 -o circle -lm circle.c
[email protected]:~/test/circle$ vim debug 
[email protected]:~/test/circle$ make circle
gcc -Wall -std=c99 -ggdb -pg -o circle -lm circle.c
  1. Создайте терминал правила шаблона.

В следующем примере объясняется эта ситуация: файл a.config получен из a.cfg, который, в свою очередь, получен из a.cfg1 (a.cfg является промежуточным файлом).

[email protected]:~/test/circle1$ ls
a.cfg1  log.txt  Makefile
[email protected]:~/test/circle1$ cat Makefile 
CP=/bin/cp

%.config:: %.cfg
        @echo "[email protected] from $<"
        @$(CP) $< [email protected]

%.cfg: %.cfg1
        @echo "[email protected] from $<"
        @$(CP) $< [email protected]

clean:
        -$(RM) *.config

Результат (поскольку правило%.config является терминальным, make запрещает создание промежуточного файла a.cfg из файла a.cfg1):

[email protected]:~/test/circle1$ make a.conf
make: *** No rule to make target 'a.conf'.  Stop.

Без двойного двоеточия для%.config результат:

[email protected]:~/test/circle1$ make a.config
a.cfg from a.cfg1
a.config from a.cfg
rm a.cfg
  1. Сделать правило, которое выполняется всегда (полезно для чистых правил). Правило не должно иметь предварительных условий!

c @desk: ~/test/circle3 $cat Makefile

CP=/bin/cp  
a.config::  
    @echo "Always" >> [email protected]  

a.config::  
    @echo "Always!" >> [email protected]  

clean:  
    -$(RM) *.config  

Результат:

[email protected]:~/test/circle3$ make a.config
[email protected]:~/test/circle3$ cat a.config 
Always
Always!
[email protected]:~/test/circle3$ make a.config
[email protected]:~/test/circle3$ cat a.config
Always
Always!
Always
Always!