Как правильно написать make-файл? (для множества файлов с однотипными именами)

Модератор: Модераторы разделов

Ответить
Аватара пользователя
Hephaestus
Сообщения: 3729
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2
Контактная информация:

Как правильно написать make-файл?

Сообщение Hephaestus »

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

В результате для листингов примеров имеем множество исходных файлов с именами типа
list1.1.c
list1.2.c
list1.3.c
list2.1.c
list2.2.c
list3.1.c
.....

Для решений задач
task1.1.c
task1.2.c
task3.1.c
task3.2.c
task3.3.c
task4.2.c

Количество файлов и полные имена заранее неизвестны.
Известно лишь, что имя состоит из префикса (list или task) и номера, состоящего из двух цифр, разделенных точкой.

Вопрос:
Возможно ли написать make-файл, который позволит скомпилировать любой из файлов по отдельности или (при необходимости) все сразу?

Я попробовал использовать маски в make-файле, но как-то не очень получилось.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20752
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Как правильно написать make-файл?

Сообщение Bizdelnick »

Напишите скрипт, который сгенерирует такой makefile.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение drBatty »

fflatx писал(а):
23.11.2013 12:14
Я попробовал использовать маски в make-файле, но как-то не очень получилось.

Код: Выделить всё

CC=gcc
CFLAGS=-c -Wall -O2
LDFLAGS=
EXECUTABLE=program
SOURCES=1.c 2.c 3.c 4.c
OBJECTS=$(SOURCES:.c=.o)

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(OBJECTS) -o $@ $(LDFLAGS)

.c.o:
    $(CC) -MD $(CFLAGS) $< -o $@

include $(wildcard   *.d)

clean:
    rm --force *.o

спрашивайте, что вам непонятно...
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение eddy »

Вот у меня для моих сниппетов такое:

Код: Выделить всё

cat ./C-snippets/Makefile
CC = gcc
LDFLAGS =
DEFINES = -DSTANDALONE -DEBUG
CFLAGS = -Wall -Werror

all : fifo_lifo bidirectional_list B-trees simple_list

%: %.c
    $(CC) $(LDFLAGS) $(CFLAGS) $(DEFINES) $< -o $@

RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
Аватара пользователя
Hephaestus
Сообщения: 3729
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение Hephaestus »

Всем спасибо.
Ваши ответы подтолкнули меня к правильному варианту.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20752
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Как правильно написать make-файл?

Сообщение Bizdelnick »

fflatx писал(а):
24.11.2013 16:52
Ваши ответы подтолкнули меня к правильному варианту.

Поделитесь, что за вариант-то? :-)
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
Hephaestus
Сообщения: 3729
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение Hephaestus »

Bizdelnick писал(а):
24.11.2013 20:07
Поделитесь, что за вариант-то? :-)
Ничего особенного.

Код: Выделить всё

PATH2 = /path/to/bins
PATH3 = /path/to/source
bins := $(basename $(wildcard *.c))
CFLAGS=-g
vpath % $(PATH2)


all: $(PATH2) $(bins)

$(PATH2):
        /bin/mkdir -p $@

$(bins): %: %.o
        gcc $(PATH3)/$? -o $(PATH2)/$@


clean:
        rm -f *.o

Для сравнения. Изначально это выглядело вот так (дети, никогда так не делайте! Это неправильно!):
Spoiler

Код: Выделить всё

PATH2 = /path/to/bins
PATH3 = /path/to/source
objects := bins list3.1 list3.2 list3.3 list3.4 list3.5 list3.6\
    list4.1    list4.2 list4.3 list4.4 list4.5\
    list5.1 list5.2 list5.3 list5.4 list5.5    list5.6 list5.7 list5.8 list5.9\
    list6.1 list6.2 list6.3 list6.4 list6.5 list6.6 list6.7 list6.8 list6.8A list6.9 list6.10 list6.10A\
    task3.1 task3.2 task3.3 task3.4    task3.5\
    task4.4 task4.5 task4.6 task4.7 task4.8\
    task5.2 task5.3 task5.4 task5.5 task5.6 task5.7 task5.8\
    task5.9_l5.2 task5.9_l5.3 task5.9_l5.4 task5.9_l5.5 task5.11\
    task6.2 task6.3 task6.4


all: $(objects)

bins:
    /bin/mkdir -p /path/to/bins

list3.1: list3.1.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list3.2: list3.2.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list3.3: list3.3.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list3.4: list3.4.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list3.5: list3.5.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list3.6: list3.6.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list4.1: list4.1.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list4.2: list4.2.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list4.3: list4.3.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list4.4: list4.4.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list4.5: list4.5.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list5.1: list5.1.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list5.2: list5.2.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list5.3: list5.3.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list5.4: list5.4.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list5.5: list5.5.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list5.6: list5.6.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list5.7: list5.7.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list5.8: list5.8.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list5.9: list5.9.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list6.1: list6.1.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list6.2: list6.2.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list6.3: list6.3.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list6.4: list6.4.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list6.5: list6.5.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list6.6: list6.6.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list6.7: list6.7.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list6.8: list6.8.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list6.8A: list6.8A.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list6.9: list6.9.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list6.10: list6.10.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

list6.10A: list6.10A.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@






task3.1: task3.1.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task3.2: task3.2.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task3.3: task3.3.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task3.4: task3.4.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task3.5: task3.5.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task4.4: task4.4.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task4.5: task4.5.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task4.6: task4.6.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task4.7: task4.7.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@
task4.8: task4.8.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task5.2: task5.2.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task5.3: task5.3.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task5.4: task5.4.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task5.5: task5.5.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task5.6: task5.6.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task5.7: task5.7.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task5.8: task5.8.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task5.9_l5.2: task5.9_l5.2.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task5.9_l5.3: task5.9_l5.3.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task5.9_l5.4: task5.9_l5.4.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task5.9_l5.5: task5.9_l5.5.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task5.11: task5.11.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task6.2: task6.2.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task6.3: task6.3.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

task6.4: task6.4.o
    cc -g $(PATH3)/$@.c -o $(PATH2)/$@

clean:
    rm -f *.o



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


Кстати, есть какая-то заморочка с шаблонами.
Например, вот так

Код: Выделить всё

$(bins): %.o
        gcc $(PATH3)/$? -o $(PATH2)/$@
работать не будет, скажет, что нет правила для %.o
Хотя в статьях такие примеры есть.

А вот так

Код: Выделить всё

$(bins): %: %.o
        gcc $(PATH3)/$? -o $(PATH2)/$@
Работает совершенно спокойно.

Вариант, предложенный drBatty тоже не заработал, потребовал правило для 1.c хотя вот это

Код: Выделить всё

.c.o:
    $(CC) -MD $(CFLAGS) $< -o $@
как бы оно и есть.

Версия make у меня из репов, судя по выводу make -v вроде GNU.
Ну, в общем, некоторые варианты не срабатывают, почему - не понял. Примеры из статей опробовать не удаётся.
Поэтому так долго не удавалось написать компактный вариант make-файла.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение drBatty »

fflatx писал(а):
25.11.2013 23:16
$(bins): %.o
gcc $(PATH3)/$? -o $(PATH2)/$@
работать не будет, скажет, что нет правила для %.o
Хотя в статьях такие примеры есть.

очевидно, что и правила есть для каждого %.o

Например в моём примере есть строка

Код: Выделить всё

include $(wildcard   *.d)

которая включает d файлы, а их -- ровно для каждого o файла
В них как раз те правила, которых у вас нет:

Код: Выделить всё

main.o: main.c /usr/include/stdc-predef.h /usr/include/stdio.h \
 /usr/include/features.h /usr/include/sys/cdefs.h \
 /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
 /usr/include/gnu/stubs-32.h \
... (многобукв)

Эти файлы создаёт сам gcc -MD, вытаскивая зависимости из C кода. Т.о. если я поменяю main.c, или /usr/include/gnu/stubs-32.h, то make это заметит, и будет собирать main.o.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение drBatty »

fflatx писал(а):
25.11.2013 23:16
.c.o:
$(CC) -MD $(CFLAGS) $< -o $@
как бы оно и есть.

это правило для *.c файлов, а для *.o тоже надо своё правило. Т.е. сначала это срабатывает для изменённых *.c файлов, вытягивая оттуда их зависимости. А потом срабатывает *.o правило, которое уже собирает o файлы (точнее оно само ничего не собирает, собирает правило выше, а правило o файлов нужно только для того, что-бы пересобирать o файлы даже когда c файлы не меняются, а меняются зависимости, например h файлы. Ну например вы обновили систему с новой glibc/printf -- надо пересобирать все ваши helloworld'ы)
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Hephaestus
Сообщения: 3729
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение Hephaestus »

drBatty писал(а):
26.11.2013 12:03
очевидно, что и правила есть для каждого %.o
Так они в статьях упоминаются, как неявные. То есть существуют, даже если я их не написал.
А если существуют, то почему не срабатывают?
Стало быть, make не находит эти самые неявные.
От чего это зависит - непонятно.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение drBatty »

fflatx писал(а):
26.11.2013 12:18
Так они в статьях упоминаются, как неявные. То есть существуют, даже если я их не написал.

телепаты всё ещё в отпуске. В каких статьях? С какого вообще перепугу? Это у меня .c.o: старый синтаксис данной подстановки: http://www.gnu.org/software/make/manual/ma...l#Pattern-Rules Правило говорит ЧТО делать с *.o файлами, точнее, как надо делать из *.c файла *.o файл.

А вот КАКИЕ *.o файлы обработать -- это правило не говорит. Вот она вам и пишет: "что мне делать, хозяин? Какие файлы собирать программой $(CC)?"

Вроде-бы так, хотя точно я сам уже не помню...
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Hephaestus
Сообщения: 3729
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение Hephaestus »

drBatty писал(а):
26.11.2013 13:57
телепаты всё ещё в отпуске. В каких статьях?
В обыкновенных, которые в Сети нашлись.
Например, вот .

Цитата
Перечень имеющихся неявных правил
........
Компиляция программ на языке Си
`n.o' автоматически получается из `n.c' при помощи команды `$(CC) -c $(CPPFLAGS) $(CFLAGS)'.


Оттуда же
Примеры шаблонных правил
Вот несколько примеров шаблонных правил, в действительности предопределенных в make. Сперва, правило, компилирующее файлы `.c' в файлы `.o':

%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@


Логика моя была примерно такая:
Согласно первой цитате, make знает, как полчить o-файл из c-файла (имеется неявное правило)
Согласно второй цитате допустимо использование шаблонов типа %.o.

Тогда, указав шаблон %.o где-то в другом правиле как зависимость, по идее можно ожидать, что make создаст из каждого c-файла соответствующий о-файл, то есть сработает неявное правило.

То есть вот это

Код: Выделить всё

$(bins): %.o
        gcc $(PATH3)/$? -o $(PATH2)/$@
вроде должно работать.
Но не работает.

Вот примерно так.
Хотя допускаю, что я чего-то не так понял и в результате "поделил на ноль", как Вы любите говорить.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение drBatty »

fflatx писал(а):
26.11.2013 14:47
Согласно первой цитате, make знает, как полчить o-файл из c-файла (имеется неявное правило)

между прочим, я своё написал ВМЕСТО него. А остальные правила кто писать будет?
fflatx писал(а):
26.11.2013 14:47
и в результате "поделил на ноль", как Вы любите говорить.

типа того.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Hephaestus
Сообщения: 3729
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение Hephaestus »

drBatty писал(а):
26.11.2013 14:52
между прочим, я своё написал ВМЕСТО него.
Ну так, а я-то ВМЕСТО ничего не писал.
Я просто использовал шаблон.

Код: Выделить всё

$(bins): %.o
        gcc $(PATH3)/$? -o $(PATH2)/$@

и ожидал что по %.o будет обработан каждый o-файл, а недостающие будут созданы из с-файлов в соответствии с неявным правилом.
Однако, не то что недостающие, даже существующие не обработались.
Так что этот момент достаточно неочевидный, на мой взгляд.
С одной стороны, есть шаблоны, с другой - не всегда они работают.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение drBatty »

да, вспомнил: неявное правило заставит make собрать main.o, в случае, если мы поменяли main.c, в этом случае УНВР. А что будет, если поменять other.h, который включён в main.c? Ничего. В лучшем случае нас обматерит ld, увидев, что у него other.o не лепится с main.o. Но это смотря как поменять, может и слепится, но криво.

Вот именно потому, я и использую фичу препроцессора cpp -MD, вытягивая main.d файл, в котором записано правило, для сборки main.o в случае, если поменялся other.h. Этот файл включается в Makefile, и заставляет make пересобрать main.o в случае, когда поменялся other.h.

Фича cpp -MD не имеет никакого отношения к компиляции, потому-то я и переопределяю правило компиляции в Makefile, а не добавляю опцию в $(CFLAGS).
fflatx писал(а):
26.11.2013 14:47
Тогда, указав шаблон %.o где-то в другом правиле как зависимость, по идее можно ожидать, что make создаст из каждого c-файла соответствующий о-файл, то есть сработает неявное правило.

Вот как раз основная задача make -- НЕ создавать каждый раз новый файл. А создавать тогда, и только когда оно НУЖНО. Т.е. если вы поменяли какой-то файл, то make собирает ТОЛЬКО то, что зависит от этого файла.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Hephaestus
Сообщения: 3729
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение Hephaestus »

drBatty писал(а):
26.11.2013 13:57
А вот КАКИЕ *.o файлы обработать -- это правило не говорит.
Ну как это - какие? Те, которые подходят под шаблон. Какие же ещё?
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение drBatty »

fflatx писал(а):
26.11.2013 15:10
между прочим, я своё написал ВМЕСТО него.

Ну так, а я-то ВМЕСТО ничего не писал.

вы моё правило написали ВМЕСТО дефолтного, а потом удивлялись, почему не работает ДРУГОЕ правило.
fflatx писал(а):
26.11.2013 15:10
С одной стороны, есть шаблоны, с другой - не всегда они работают.

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

Если ничего не изменилось, make скажет -- "делать нечего".
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Hephaestus
Сообщения: 3729
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение Hephaestus »

drBatty писал(а):
26.11.2013 15:14
Вот как раз основная задача make -- НЕ создавать каждый раз новый файл. А создавать тогда, и только когда оно НУЖНО. Т.е. если вы поменяли какой-то файл, то make собирает ТОЛЬКО то, что зависит от этого файла.
Да я не возражаю. Замечательно.
Огорчает другое: Как Вы заметили выше, make не знает, какие файлы обрабатывать по шаблону, хотя, казалось бы, это не должно вызывать затруднений.
Если бы просто не нашлось файлов, подходящих под шаблон - это ладно, но ведь вообще не отрабатывает, даже существующие файлы.
Ругается на отсутствие правила - вот что плохо.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение drBatty »

fflatx писал(а):
26.11.2013 15:15
Ну как это - какие? Те, которые подходят под шаблон. Какие же ещё?

шаблон -- дело десятое. Если просто под шаблон подходит, то make ничего с этим делать не будет, она будет делать из *.c файл *.o ТОЛЬКО если видит, что *.o нету, или он есть, но слишком старый по сравнению *.c. Ну или зависимость изменилась -- какой-нить *.h файл например. Линкер вообще не видит header'ов, он видит только obj файлы. Потому, если вы изменили header, то вам нужно пересобрать все obj, которые его прямо или косвенно включают.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Hephaestus
Сообщения: 3729
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение Hephaestus »

drBatty писал(а):
26.11.2013 15:19
вы моё правило написали ВМЕСТО дефолтного
Не-не. Не Ваше правило. Из Ваших я ничего не брал.
Я попробовал использовать Ваш код целиком как есть, он ругнулся на отсутствие правила и я пошёл читать маны, чтобы в нём разобраться.
Больше я его не использовал.

А не сработало моё правило с шаблоном %.o, которое я писал, ориентируясь на маны и статьи.
Я же специально привёл строчку кода.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение drBatty »

fflatx писал(а):
26.11.2013 15:22
Ругается на отсутствие правила - вот что плохо.

fflatx писал(а):
25.11.2013 23:16

Код: Выделить всё

$(bins): %: %.o
        gcc $(PATH3)/$? -o $(PATH2)/$@

Работает совершенно спокойно.

fflatx писал(а):
26.11.2013 14:47

Код: Выделить всё

$(bins): %.o
        gcc $(PATH3)/$? -o $(PATH2)/$@

вроде должно работать.
Но не работает.

во втором случае она не может раскрыть процент. Т.е. вы ей сказали, что надо "взять файлы $(bins)", но не сказали, что делать с их именами. Хотя потом имеете наглость писать $@, хотя
$@
The file name of the target of the rule. If the target is an archive member, then ‘$@’ is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), ‘$@’ is the name of whichever target caused the rule's recipe to be run.

рассчитывая, что она распарсит как Pattern Rules, но процентик, который и будет считаться за имя исполняемого файла вы забыли написать.

fflatx писал(а):
26.11.2013 15:29
Не-не. Не Ваше правило. Из Ваших я ничего не брал.

можно на "ты"? Меня корёжет Ваше ВЫ (:

fflatx писал(а):
26.11.2013 15:29
А не сработало моё правило с шаблоном %.o

потому-что %.o это не шаблон, а то, НА ЧТО нужно менять шаблон(в вашем случае просто %).
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Hephaestus
Сообщения: 3729
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение Hephaestus »

drBatty писал(а):
26.11.2013 15:26
Если просто под шаблон подходит, то make ничего с этим делать не будет, она будет делать из *.c файл *.o ТОЛЬКО если видит, что *.o нету, или он есть, но слишком старый по сравнению *.c.
Да ради Бога, я разве против?
Есть цель: получить бинарник. Бинарника в наличии нету. Значит, выполняются инструкции, указанные для данной цели.
Но данная цель зависит от o-файла. Если о-файл есть - пожалуйста, создавай бинарник.
И шаблон типа %.o здесь помехой быть не должен. Под него подходят все файлы с расширением .o Нашлись - используй.
Но не использует, просит правило персонально для %.o.
Не то, что файлы не изменились, а именно правило просит.
Вот что сбивает с толку.

drBatty писал(а):
26.11.2013 15:39
можно на "ты"? Меня корёжет Ваше ВЫ (:
Всё-таки корёжит? Хотя я в своё время пытался прояснить этот момент. :)
Ладно, договорились. Можно на "ты". В обе стороны.

drBatty писал(а):
26.11.2013 15:39
потому-что %.o это не шаблон
А вот это что-то новое, по крайней мере, в той статье, что я цитировал это называют шаблоном.
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение drBatty »

fflatx писал(а):
26.11.2013 15:42
И шаблон типа %.o здесь помехой быть не должен. Под него подходят все файлы с расширением .o Нашлись - используй.

ты не правильно понимаешь то, что там дальше написано:

Код: Выделить всё

gcc $(PATH3)/$? -o $(PATH2)/$@

вот тут $? меняется на %.o, а $@ меняется на %, а в этот % по очереди вставляются все цели из списка $(bins). Т.е. если у тебя $(bins)==="x y z", то она создаёт три команды

Код: Выделить всё

gcc path3/x.o -o path2/x
gcc path3/y.o -o path2/y
gcc path3/z.o -o path2/z

конечно если файлов цели x y z нет, или они старые.

Но для этого ей надо знать три вещи:
1. список целей (x y z)
2. шаблон имени цели %
3. шаблон имени исходного файла %.o (тут исходником выступает obj, потому-что это линкер работает)
fflatx писал(а):
26.11.2013 15:42
Всё-таки корёжит?

так только боты пишут.
ИМХО
fflatx писал(а):
26.11.2013 15:42
А вот это что-то новое, по крайней мере, в той статье, что я цитировал это называют шаблоном.

м... Как раз таки это шаблон(template), а вот просто % -- это pattern. Т.е. % это ЧТО ИСКАТЬ, а %.c это НА ЧТО МЕНЯТЬ. В русских источниках перепутано часто... Нет у нас слова pattern в таком смысле. Близко "образец", но не то.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Hephaestus
Сообщения: 3729
Статус: Многоуважаемый джинн...
ОС: Slackware64-14.1/14.2
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение Hephaestus »

drBatty писал(а):
26.11.2013 16:09
вот тут $? меняется на %.o, а $@ меняется на %
Во! Вот это как раз и не очевидно.
Вроде бы $? - это список зависимостей, которые новее, чем цель. Сюда подставляется %.c - это ясно.
А вот $@ - это сама цель, т.е. $(bins) и с чего вдруг $@ меняется на % - непонятно.
Может оно и так, но вот не очевидно ни разу.

А кстати, эту кухню (что на что заменяется) можно как-нибудь увидеть в режиме отладки или ещё как?
Я пробовал make -d, но проясняет не очень, если честно.

drBatty писал(а):
26.11.2013 16:09
так только боты пишут.
Ну вот, дожили. Правила вежливости соблюдаются только ботами. Больше некому. :laugh:
Пускай скрипят мои конечности.
Я - повелитель бесконечности...
Мой блог
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Как правильно написать make-файл?

Сообщение drBatty »

fflatx писал(а):
26.11.2013 18:29
Вроде бы $? - это список зависимостей, которые новее, чем цель. Сюда подставляется %.c - это ясно.
А вот $@ - это сама цель, т.е. $(bins) и с чего вдруг $@ меняется на % - непонятно

то, что на $ начинается, это никакой не список, а одно имя. Вот $? это одно имя из списка $(bins)

потом из имени выдёргивается % (в нашем случае это всё имя), и пихается в шаблон %.c ; что получилось вставляется вместо $@

похожая схема используется в программе rename(1), её сейчас рядом обсуждают.
fflatx писал(а):
26.11.2013 18:29
А кстати, эту кухню (что на что заменяется) можно как-нибудь увидеть в режиме отладки или ещё как?

без понятия. Я сам не знал про make -d.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Ответить