LINUX.ORG.RU

Повторяющиеся правила в Makefile

 ,


0

1

Как избавиться от повторяющихся правил в makefile? Объединить все правила в один макрос?

$(objdir)/%.o: $(common_dir)/%.cpp
	@echo Compiling $<
	$(CC) $(INCLUDE_PATH) $(CFLAGS) -c $< -o $@

$(objdir)/%.o: $(worker_dir)/%.cpp
	@echo Compiling $<
	$(CC) $(INCLUDE_PATH) $(CFLAGS) -c $< -o $@

...

Ответ на: комментарий от Bad_ptr

У меня исходники раскиданы по разным каталогам

nerdogeek
() автор топика

Можно определить функцию (в данном случае от каталога), а потом $(eval $(call ...))

info make поможет

ogronom
()

Например так:

$ mkdir build a b
$ touch a/a.c b/b.c
$ cat Makefile 
objects := build/a/a.o build/b/b.o

all: $(objects)

build/%.o: %.c
        cc -c -o $@ $<
$ make -n
cc -c -o build/a/a.o a/a.c
cc -c -o build/b/b.o b/b.c
gv
()
Ответ на: комментарий от gv

Да, это вариант, но у меня отдельно правила для сборки .o, отдельно правило линковки этих .o в исполняемый. Получается аналогичная ситуация, только наоборот, будет одно правило для сборки цпп-шников, но мн-во правил для сборки в исполняемый :)

nerdogeek
() автор топика
Ответ на: комментарий от ei-grad

К сожалению, такой вариант не работает. Жаль что make не позволяет объеденять различные несвязанные пары цель:реквезит с одинаковыми командами.

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

Да, это вариант, но у меня отдельно правила для сборки .o, отдельно правило линковки этих .o в исполняемый. Получается аналогичная ситуация, только наоборот, будет одно правило для сборки цпп-шников, но мн-во правил для сборки в исполняемый :)

Не понял. Приведите пример?

gv
()
Ответ на: комментарий от ei-grad
CC := g++
RFLAGS := -Wall -pedantic -pthread -O3
DFLAGS := -Wall -pedantic -pthread -O0 -ggdb

ifneq ($(MAKECMDGOALS),debug)
CFLAGS := $(RFLAGS)
else
CFLAGS := $(DFLAGS)
endif

INCLUDE_PATH := -I/usr/include/boost -Isrc

RM := rm -rf

LIBS := -lboost_system -lboost_thread -lboost_program_options -lboost_filesystem -lrt
LIB_PATH := /usr/lib


srcdir := src
objdir := objs
depdir := deps

common_dir := $(srcdir)/common
worker_dir := $(srcdir)/worker

COMMON := log config common
COMMON_OBJS := $(addprefix $(objdir)/, $(addsuffix .o, $(COMMON)))

WORKER := pyexec pyserver
WORKER_OBJS := $(addprefix $(objdir)/, $(addsuffix .o, $(WORKER)))

OUT := pyserver pyexec

ALL_CPP := $(COMMON) $(WORKER)
DEPENDS := $(addprefix $(depdir)/, $(addsuffix .d, $(ALL_CPP)))


all: installdirs $(DEPENDS) $(OUT)

debug: all

installdirs:
@mkdir -p $(objdir) $(depdir)

$(OUT): $(COMMON_OBJS) $(WORKER_OBJS)
$(eval main_obj= $(addprefix $(objdir)/, $(addsuffix .o, $@)))
$(CC) $(main_obj) $(COMMON_OBJS) -o $@ $(INCLUDE_PATH) -L$(LIB_PATH) $(LIBS) $(CFLAGS)

define BUILD_SRC
@echo Compiling $<
$(CC) $(INCLUDE_PATH) $(CFLAGS) -c $< -o $@
endef

$(objdir)/%.o: $(common_dir)/%.cpp
$(BUILD_SRC)
$(objdir)/%.o: $(worker_dir)/%.cpp
$(BUILD_SRC)

define BUILD_DEPS
$(CC) -MM $< > $@ $(INCLUDE_PATH)
@sed -i "s/^/$(objdir)\//" $@
@cat $@ >> $(depdir)/.depend
endef

$(depdir)/%.d: $(common_dir)/%.cpp
$(BUILD_DEPS)
$(depdir)/%.d: $(worker_dir)/%.cpp
$(BUILD_DEPS)

-include $(depdir)/.depend

clean:
$(RM) $(OUT) $(objdir) $(depdir)


.PHONY: all clean installdirs debug
nerdogeek
() автор топика
Ответ на: комментарий от nerdogeek

Добавил код выше

А, понял.

Получается аналогичная ситуация, только наоборот, будет одно правило для сборки цпп-шников, но мн-во правил для сборки в исполняемый :)

Если проект большой, make IMHO лучше не использовать. В проектах с make обычно эту проблему решают так:

  • В корне лежит common.inc с примерно таким содержимым:
    $(TARGET): $(OBJECTS)
        $(LD) ....
    
    %.o: %.cpp:
        $(CC) ....
    
  • В корне лежит Makefile, который вызывает make во всех подкаталогах.
  • В каждом подкаталоге лежит Makefile такого вида:
    OBJECTS := foo.o bar.o
    TARGET := baz
    
    include ../common.inc
    

    Когда через некоторое время переменных вроде TARGET и OBJECTS становится дофига, разбираться в этом уже тяжело.

gv
()
Ответ на: комментарий от nerdogeek

Похожий вариант видел в ядре линукса, но... попалась на глаза эта статья: http://aegis.sourceforge.net/auug97.pdf

О, спасибо, надо почитать.

В общем, я обычно выбираю между небольшим makefile-ом с копипастой (в которой только переменные, вроде $(LD) $(LDFLAGS) ...) и какими-нибудь CMake/SCons. Ну и в automake эта проблема тоже решена.

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