2013-09-17 3 views
0

У меня есть Makefile, который компилирует код C на Ubuntu Linux 13.04. Это выглядит примерно так:Сделать переупорядочивание правил?

CC=gcc 
CFLAGS=-c -Wall 
LDFLAGS=-lm 
SOURCES=$(wildcard *.c) 
OBJECTS=$(SOURCES:.c=.o) 
EXECS=$(SOURCES:%.c=%) 

all: $(OBJECTS) $(EXECS) 
.c.o: 
     $(CC) $(CFLAGS) $< -o [email protected] 
.o.: 
     $(CC) -o [email protected] $^ $(LDFLAGS) 

Теперь ld хочет $(LDFLAGS) появляться в конце строки, в которой я поставил его выше. Когда я бегу make на этом Makefile я получаю следующий вид продукции:

$ make 
gcc -c -Wall FILENAME.c -o FILENAME.o 
... 
gcc -lm FILENAME.o -o FILENAME 
... 

Почему -lm появляется после того, как компилятору на второй строке, а не в конце строки?

ответ

3

Из этого правила:

.o.: 
     $(CC) -o [email protected] $^ $(LDFLAGS) 

не имеет никакого эффекта. Вы говорите, как создать литеральный файл с именем .o., но поскольку вы не пытаетесь создать этот файл, это правило игнорируется. Вы должны использовать просто .o (ни один другой период), если вы пытаетесь указать правило с одним суффиксом.

Поскольку ваш make-файл не определяет правило для построения FILENAME, make выполняет поиск встроенной библиотеки неявных правил, чтобы найти его для создания исполняемого файла. В стандартной встроенной библиотеке правил переменная LDFLAGS предназначена для флагов компоновщика, таких как -L и т. Д., Которые определяют пути и должны быть представлены перед всеми библиотеками. Переменная LDLIBS предназначена для указания библиотек для ссылки, например -lm.

+1

BTW, я не рекомендую использовать правила суффикса. Вы уже готовы использовать GNU make с помощью '$ (wildcard ...)' и т. Д., Чтобы вы могли использовать шаблонные правила. Их гораздо проще читать и понимать. Или, не утруждайте себя написанием каких-либо правил и используйте встроенные правила make! Это даже лучше, если у вас нет требования, которое они не могут удовлетворить. – MadScientist

+0

И PPS, вы можете увидеть встроенную библиотеку правил и переменных make, запустив 'make -p -f/dev/null'. – MadScientist

+0

Хм. Мое понимание заключалось в том, что для правила 'all' требуется' $ (OBJECTS) 'быть построено как предварительное условие для $ (EXECS)'. Почему это не так? – snim2

Смежные вопросы