LINUX.ORG.RU

Makefile


0

2

Пишу Makefile для небольшого проекта. Хочу что бы все по феншую, или хотя бы не в одной куче. Имеется следующая структура каталогок

./include - общие для server и client заголовочный файлы
./src - общие для server и client сурсные файлы
./server - специфичные исходники
./client - специфичные исходники
./bin - хотелосьбы чтобы сюда клались все .o файлы и файл конечной программы

Как я вижу себе расположение Makefil'ов

./src/Mikefile - отчетает за получение *.o для всех *.c расположенных в нем (по возможности распологать их в ../bin)
./server/Makefile - отвечает за получение *.о для всех *.с расположенных в нем
./Makifile - содержит два правила для сборки либо client либо server

Читаю gnu make manual, но вопросов и непоняток куча. Начал с ./src/Makefile

CXX	= g++
LD	= g++
CXXFLAGS += -std=c++0x -I../include

objects := $(patsubst %.c,%.o,$(wildcard *.c))
object = *.o

vpath %.hpp ../include

persone.o : persone.hpp
address.o : address.hpp

.PFONY : clean
clean: 
	-rm -f $(object) 
теперь по порядку:

1. в правие clean при использовании $(objects) оно пустое вместо того чтобы содержать все .o файлы для .c файлов. Так и не понял почему.

2. Как правильно использовать механизм $(CXX) -MМ *.c для того чтобы не ручками писать для каждого правила набор пререквизитов а получать его автоматически ? И возможно ли такое вообще ?

2.1 Если пунк 2 невозможен, то тогда получается что нужно все подключаемые хедеры руками перечислять ?

3. Если возможно (2) то тогда как правильно сделать вместо перечисления правил (persone.o, address.o,...) шаблонное статическое правило для сборки всех объектных файлов для всех .c файлов с указанием для них в качестве пререквизитов значения полученные в (2)

4. Как можно сделать так чтобы полученные *.o файлы лежали не в этой же директории а в нужной мне (../bin)

-------------------------------------------------------------------

Опуская все это написал второй makefile

./server/Makefile

CXX	= g++
LD	= g++
LDFLAGS += -lboost_system -lboost_date_time -lboost_serialization -lmysqlcppconn
CXXFLAGS += -std=c++0x -I/usr/local/include -I/usr/local/include/cppconn

object = persone.o main.o database_helper.o persone_db.o address.o address_db.o
#objects := $(patsubst %.c,%.o,$(wildcard *.c))

vpath %.o ../src # в надежде что будет производиться поиск в том месте где предполагается что они там лежат, а не в текущей директории
vpath %.hpp ../include

server: $(object)
	$(LD) $(LDFLAGS) $(object) -o server

include ../src/Makefile # для того чтобы загрузи, или выполнить правила указанные в этом файле, чтобы получить нужные .о

main.o: main.cpp persone.hpp persone_db.hpp address.hpp address_db.hpp database_helper.hpp
	$(CXX) $(CXXFLAGS) -c main.cpp
database_helper.o: database_helper.hpp database_helper.cpp
	$(CXX) $(CXXFLAGS) -c database_helper.cpp
persone_db.o: persone_db.cpp persone_db.hpp persone.hpp address_db.hpp address.hpp database_helper.hpp
	$(CXX) $(CXXFLAGS) -c persone_db.cpp
address_db.o: address_db.cpp address_db.hpp address.hpp persone.hpp persone_db.hpp database_helper.hpp
	$(CXX) $(CXXFLAGS) -c address_db.cpp

.PHONY : clean
clean :
	-rm -f server $(object)
Вопрос:

1. Самый главный. Строчку include ../src/Makefile не приводит к выполнению правил. В следствии чего при линковке в главном правиле gcc сурово ругается на undefine reference.

2. Остальные вопросы такие же, правильно юзание clean, поместить *.o в определенную директория, и взять из от туда же.

------------------------------------------------------------

Дальше делать пока смысла нет. Если поможите разобраться с этими вопросами то далее все по аналогии будет.

____________________________________________________________

Граждони форумчани, помогите разобраться :)


Кто сказал Cmake?

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

тобишь полтора дня в пустую :(

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

1. Либо потому что ищешь .c вместо .cpp, либо потому что не там ищешь (у тебя в примере поиск идет в текущей директории).

2, 3. Повытаскивал частично из своего Makefile:


PROJECT:=helloworld

CC:=gcc -std=c99
CFLAGS:=-Wall -Wextra -g -fpic -O2
LINKER:=${CС}

C_EXT:=.c
C_DEP_EXT:=.d
C_OBJ_EXT:=.o

export D_MSG="DEP \t"
export L_MSG="LINK \t"
export C_MSG="CMPL \t"

#you can use $(wildcard) instead of $(shell find). I need find...
C_SRC:=$(shell find src -name *${C_EXT})
OBJS:=$(patsubst %${C_EXT},%${C_OBJ_EXT},${C_SRC})


.PHONY:all binary library clean __prep deps-make run test-run

all: binary
binary: __prep ${PROJECT}
library: __prep lib${PROJECT}.so
__prep: deps-make

deps-make: ${C_DEP}

${PROJECT}: ${OBJS}
        @echo -e ${L_MSG} $@
        @${LINKER} ${LFLAGS} ${LIB} ${OBJS} -o $@

#deps
%${C_DEP_EXT}:
        @echo -e ${D_MSG} $@
        @${CC} ${INC} -MM -MT "$@ ${@:${C_DEP_EXT}=${C_OBJ_EXT}}" ${@:${C_DEP_EXT}=${C_EXT}} -o $@

#srcs
%${C_OBJ_EXT}:
        @echo -e ${C_MSG} $@
        @${CC} ${CFLAGS} ${INC} ${@:${C_OBJ_EXT}=${C_EXT}} -c -o $@

4. В правилах #srcs указывать нужный -o (что-то вроде ../bin/$@)

Опять цифры:

1. Хз, как обрабатываются инклуды. Никогда не пользовал. Вместо этого делаю внутренние вызовы make.

В помощь: http://www.opennet.ru/docs/RUS/make_compile/make.htm

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

О! Важный фикс.

SRC_DIRS:=$(shell find src -type d)

#в конце makefile - включение dep-файлов зависимостей:
include $(wildcard $(patsubst %,%${C_DEP_EXT},${SRC_DIRS}))

Если директория одна, можно не париться с SRC_DIRS и искать в текущей или где там лежат исходники...

staseg ★★★★★
()

в правие clean при использовании $(objects)

Не в том каталоге ищешь?

2. Как правильно использовать механизм $(CXX) -MМ *.c для того чтобы не ручками писать для каждого правила набор пререквизитов а получать его автоматически ? И возможно ли такое вообще ?

Возможно. Использовать как-то так (отдельные цитаты из разных частей makefile-а) :

_TARGETS     := $(addprefix $(BUILDDIR_T)/, $(TARGETS))
_TARGETS_1X1 := $(addprefix $(BUILDDIR_T)/, $(TARGETS_1X1))
_OBJS        := $(addsuffix .o,$(addprefix $(BUILDDIR_O)/, $(SOURCES)))
_PICOBJS     := $(addsuffix .pic.o,$(addprefix $(BUILDDIR_O)/, $(SOURCES)))
_OBJS_1X1    := $(addsuffix .o,$(addprefix $(BUILDDIR_O)/, $(TARGETS_1X1)))
_PICOBJS_1X1 := $(addsuffix .pic.o,$(addprefix $(BUILDDIR_O)/, $(TARGETS_1X1)))
_DEPS := $(sort $(_OBJS) $(_PICOBJS) $(_OBJS_1X1) $(_PICOBJS_1X1))


CMD_BUILD_O = \
	$(Q)echo "CC      "$(subst $(M_DIR_ROOT)/,,$@) && \
	mkdir -p $(dir $(M_DIR_DEP)/$@.dep)&& \
	mkdir -p $(dir $@) && \
	$(CC) $(CFLAGS) $(CFLAGS_O) $(CFLAGS_O_$(basename $(notdir $@))) -c $(1) -o $@ -MD -MP -MF $(M_DIR_DEP)/$@.dep


$(BUILDDIR_O)/%.o: %.c $(STDDEPS)
	$(call CMD_BUILD_O, $<)

-include $(addsuffix .dep, $(addprefix $(M_DIR_DEP)/, $(_DEPS)))

4. Как можно сделать так чтобы полученные *.o файлы лежали не в этой же директории а в нужной мне

Бери полные пути и строй на их основе правила:

$(BUILDDIR_O)/%.o: %.c $(STDDEPS)
	$(call CMD_BUILD_O, $<)

geekless ★★
()
Ответ на: О! Важный фикс. от staseg

Либо потому что ищешь .c вместо .cpp лажанул :)

а что делает правило ?

 #deps %${C_DEP_EXT}: ... 
правило
 #srcs %${C_OBJ_EXT}: 
строит .o для всех .с ? вообще не врубаюсь как оно у вас работает :)

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

>Сколько извращений... CMake осиль наконец.

Цыц, не руки прочь от тёплого лампового make-.а

geekless ★★
()

Собственно, вот мой велосипедный сборщик с отслеживанием зависимостей

Makefile.build: http://pastebin.com/jeXXvqz3

В главном makefile-е экспортируем переменные, которые видны всем зависимым скриптам и затем делаем как-то так:

include $(M_DIR_ROOT)/Makefile.include

MAKEFILES += $(M_DIR_ROOT)/Makefile.include
MAKEFLAGS += --no-print-directory

M_MAKEBUILD = $(M_DIR_ROOT)/Makefile.build
export M_MAKEBUILD

ifdef C

GOALS = $(if $(MAKECMDGOALS),$(MAKECMDGOALS),all)

$(GOALS):
	$(MAKE) -C $(C) $(MAKECMDGOALS)

.PHONY: $(GOALS)

else

all:
	$(Q)make -C dist
	$(Q)make -C utils
	$(Q)make -C src

clean:
	rm -f *~ core
	make -C dist clean
	make -C utils clean
	make -C src clean
endif

А в подкаталогах с исходниками вот так:

NAMES = $(basename $(wildcard *.c))

BUILDDIR     = $(M_P_PROGRAMS)
TARGETS_1X1  = $(NAMES)
TARGET_HELPFILES = $(NAMES)
USING_LIB_SO = 
USING_LIB_A  = 


include $(M_MAKEBUILD)

Минус такого подхода — если надо собрать отдельный подкаталог, сборку надо запускать всё равно через главный makefile:

$ cd src/подкаталог; make # не пашет

$ make -C src/подкаталог # и так не пашет

$ make C=src/подкаталог # работает

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

Мне было лень «упрощать» файл, заменяя в нем ${...ext} и все прочее. И все равно ведь что-нибудь упустил бы :) Значение ${...ext}-переменных, я надеюсь, было понятно. Это расширения .c .d и .o.

В общем идея такая:

%.d: - правило для любого dep-файла (файла зависимостей) (dep - это цель при генерировании зависимостей по файлам исходников). Аналогично, %.o: - правила создания объектных файлов. «Вызываются» %.d:-правила из deps-make, %.o:-правила - из '${PROJECT}: ${OBJS}'. В генерируемых dep-файлах дополнительно описываются зависимости фактически для каждого dep- и объектного файла, потом эти файлы подключаются в Makefile, то есть получается что-то вроде:

cat src/confparser.dxx
src/confparser.dxx src/confparser.oxx: src/confparser.cpp \
 src/confparser.h include/stInternal/vector.h \
 include/stInternal/allocator.h include/stLogger.h include/stConfig.h \
 include/stRange.h include/stKv.h src/item.h

(сишный файл с ходу не нашел, .dxx и .oxx - это по сути .d и .o)

Если это не понятно, лучше внимательно прочитать мануал с начала до конца, сылку я дал выше.

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

спасибо. Я предполагал что оно все там не просто :) Попробую осилить высокие технологии в лице CMake :)

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

Если знаком с питоном - scons.

anonymous
()

Про autotools никто не сказал? ЛОР действительно уже не торт.

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