LINUX.ORG.RU

Шаблонное правило для сборки объектника с автоматичским определением списка зависимостей?

 gnumake,


0

1

Сабж. Хочется чего то такого

src/%.o: src/%.cpp правильные зависимости
    $(CXX) -o $@ -c $< 
но откуда этот список правильных зависимостей взять? Хочется заюзать g++ -M, в итоге приходиться извращаться каким то вот таким образом
ifndef MODULE
src/%.o: src/%.cpp include/*;   @$(MAKE) --no-print-directory MODULE:=$(basename $@).cpp $@
else
$(strip $(dir $(MODULE))$(subst \,,$(shell $(GCC) $(CXXOPT) -M $(MODULE))))
    $(CXX) -o $(basename $(MODULE)).o -c $(MODULE)
endif
Как то это можно сделать более прямо и менее извращенно?

ЗЫ Вариант с выводом g++ -M в отдельный файл с зависимостями я знаю, он считается более прямым?;-)

★★★★★

Последнее исправление: AIv (всего исправлений: 1)

Вариант с выводом g++ -M в отдельный файл с зависимостями я знаю, он считается более прямым?

Да. И не только для GNU make и gcc. Чем он тебя не устроил? Это всего лишь один лишний include.

E ★★★
()

cmake - не?

anonymous
()
Ответ на: комментарий от E

Например

SOURCES = $(wildcard *.cpp)
OBJ = $(addprefix tmp/,$(SOURCES:.cpp=.o))
CXXFLAGS = -MD -MP \ # <<<<<<<<<<<<< here...
    -std=c++0x $(WARNINGS)

$(BIN): $(OBJ)
    $(CXX) $(LIBS) -o $@ $^

tmp/%.o: %.cpp
    @echo Compiling $<...
    @$(CXX) $(CXXFLAGS) -c $< -o $@

$(shell mkdir -p tmp) 
-include $(OBJ:%.o=%.d)   # <<<<<<<<<<<<< ...and here
E ★★★
()

Зависимости действительно часто хранят отдельно. Бывает неудобства при их изменении (так как зависимости обычно отстают на один билд от исходников), но некоторые извращаются и исправляют это (тоже двумя вызовами компилятора, вроде, давно читал ту статью).

xaizek ★★★★★
()
Последнее исправление: xaizek (всего исправлений: 1)
Ответ на: комментарий от E

Я уже не помню, я этой фигней давно занимался - был там какой то свой косяк;-(

Сейчас пришлось рефакторить систему сборки - а там такое вот.

AIv ★★★★★
() автор топика
Ответ на: комментарий от xaizek

Эту шню я видел еще в руководстве по make. В моем вариант тоже приходиться че то аналогичное делать (вешать изначальные зависимости всех от всех что бы не прощелкать изменения).

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

ЗЫ тьфу, забыл объектник в .PRECIOUS сунуть;-(

AIv ★★★★★
() автор топика
Последнее исправление: AIv (всего исправлений: 1)
Ответ на: комментарий от xaizek

Эта статья не актуальна уже.

Способ от E содержит один вызов компилятора на объектник, зависимости не отстают от исходников (вернее, в случае если отстают, затронутые объектники всё равно пересоберутся).

NeXTSTEP ★★
()
Ответ на: комментарий от NeXTSTEP

Про флаг -MP не знал и думал, что с переименованием/удалением зависимости без извратов не разобраться. Статья и другие моменты упоминает, но в этом плане, видимо, не актуальна.

xaizek ★★★★★
()
25 декабря 2016 г.
Ответ на: Например от E

Чому в CXXFLAGS, а не CPPFLAGS? Ведь это https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Preprocessor-Options.html
Чому -MD, а не -MMD?
Чем плоха идея писать -include $(shell find . -type f -name '*.d'), с учётом того, что я не хочу заносить сырцы и объектники в переменную, а хочу указывать явно: prog1: obj1.o obj2.o (у меня N бинарников).

utf8nowhere ★★★
()
Ответ на: комментарий от utf8nowhere

Чому в CXXFLAGS

Кроссплатформенные привычки.

Чому -MD, а не -MMD

Кроссплатформенные привычки. Для стабильных систем никакой разницы, в принципе, можно писать -MMD.

Чем плоха идея писать

Пиши как хочешь, эффект один и тот же. Вопрос личного удобства.

E ★★★
()
Ответ на: комментарий от E

Пиши как хочешь, эффект один и тот же.

Ну я написал. Это нормально, что make начинает интересоваться всеми пустыми правилами для хэдеров? Дёргает для них gcc чтоб тот рассказал мне про «warning: #pragma once in main file»

utf8nowhere ★★★
()
Ответ на: комментарий от utf8nowhere

Нет, это ненормально. Ты всё-таки что-то делаешь не так. Походу, у тебя хедеры попали в таргеты и GNU make пытается их собрать по каким-то implicit правилам. Поизучай содержимое своих *.d файлов и подробный вывод make -p.

E ★★★
()
Ответ на: комментарий от E

Minimal NOT working example

$ tree
.
├── include
│   └── header.h
├── main.cpp
├── Makefile
└── subdir
    └── main.cpp

header.h: #pragma once
Makefile:

CPPFLAGS=-I./include -MMD -MP

all: main subdir/main

-include $(shell find . -type f -name '*.d')
main.cpp && subdir/main.cpp:
#include <header.h>
int main() {}
Дёргаем make в чистом дереве:
$ make
g++  -I./include -MMD -MP   main.cpp   -o main
g++  -I./include -MMD -MP   subdir/main.cpp   -o subdir/main
main.d: main: include/header.h (странно, что нет phony target)
subdir/main.d: subdir/main: include/header.h
Теперь просто потрогаем header.h: $ touch include/header.h и вызовем make:
$ make
g++  -I./include -MMD -MP   main.cpp include/header.h   -o main
include/header.h:1:9: warning: #pragma once in main file
 #pragma once
         ^~~~
g++  -I./include -MMD -MP   subdir/main.cpp include/header.h   -o subdir/main
include/header.h:1:9: warning: #pragma once in main file
 #pragma once
         ^~~~
Здрасте приехали.

utf8nowhere ★★★
()
Ответ на: Minimal NOT working example от utf8nowhere

Лечится добавлением зависимостей бинарников от объектных файлов:

CPPFLAGS=-I./include -MMD -MP

all: main subdir/main

main: main.o
subdir/main: subdir/main.o

-include $(shell find . -type f -name '*.d')
Тогда в .d-файлах появляются нормальные таргеты:
main.o: main.cpp include/header.h

include/header.h:
И после touch include/header.h всё собирается нормально:
$ make
g++  -I./include -MMD -MP  -c -o main.o main.cpp
cc   main.o   -o main
g++  -I./include -MMD -MP  -c -o subdir/main.o subdir/main.cpp
cc   subdir/main.o   -o subdir/main

utf8nowhere ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.