AutoMake и зависимости проекта
У меня есть проект, который я хочу построить с помощью automake. Проект состоит из различных компонентов или модулей, и существуют межмодульные зависимости, которые требуют, чтобы проект был построен в определенном порядке.
Например:
project dir/
module1 (core C shared lib)
module2 (C++ shared lib wrapper around module 1)
module3 (C++ application with dependency on module2)
module4 (C library with dependency on module1)
module5 (C application with dependency on module4)
Я относительно новичок в автомобилестроении, но я (почти) знаю, как использовать его для успешного создания отдельного проекта.
Я хотел бы иметь "главный" файл проекта (если это возможно), в котором указывается порядок сборки модулей проектов, выполняются модульные тесты и происходит сбой всего процесса сборки, если либо:
- Один из модулей не может быть собран
- Один из модулей не проходит модульное тестирование
Как мне написать такой "главный проект" (или вызвать любой другой механизм) для создания проектов, которые имеют много интермодульных зависимостей?
2 ответа
Если вы используете autotools, то вы можете также использовать automake. Верхний уровень Makefile.am
может предоставить список подкаталогов, которые расположены по порядку, например:
SUBDIRS = module1 module2 module3 module4 module5
Подкаталог Makefile.am
может добавить цели для тестов, вызванных командой 'make check', которая при необходимости приведет к сборке:
check_PROGRAMS = t_module1
t_module1_SOURCES = t_module1.c
t_module1_LDADD = ./libmodule1.la
Нам нужно многому научиться, и определить наилучшую текущую практику может быть сложно, но если вы используете автоинструменты, вы привыкнете к этой ситуации.
РЕДАКТИРОВАТЬ:
info automake
предоставляет справочную документацию - но это плохой учебник. Одно из лучших руководств, с которыми я сталкивался, можно найти здесь.
Я столкнулся с той же проблемой и обнаружил, что решение для чистого автоинструмента очень сложно запустить, потому что скрипт configure, например, для module4
зависит от установки module1
,
Собранный вручную Makefile и скрипт configure для этой ситуации довольно легко сгенерировать. Я вставил ниже проекта quickSTORM Makefile. Он используется для компоновки вне дерева (исходный каталог и каталог сборки).
TARGETS=any_iterator libb64 readsif cs_units dStorm-doc simparm andorcamd rapidSTORM plugin-andorsif fitter master
all:
# Project dependencies: Any project whose configure run depends upon other projects has a line here
andorcamd.prerequisites-installed : $(addsuffix .installed-stamp,libb64 simparm cs_units)
rapidSTORM.prerequisites-installed : $(addsuffix .installed-stamp,simparm cs_units libb64 any_iterator)
plugin-andorsif.prerequisites-installed : $(addsuffix .installed-stamp,rapidSTORM readsif)
master.prerequisites-installed fitter.prerequisites-installed : $(addsuffix .installed-stamp,rapidSTORM)
# [Autoconf substitutions snipped here]
# The .options files control configuration of subdirectories. They are used in %.configured-stamp
vpath %.options $(srcdir)/options:$(builddir)
RULES = all check install installcheck dist distcheck
# All standard rules have a simple template: Execute them for each
# subdirectory after configuring it and installing all prerequisite
# packages, and re-execute them whenever
# the source files changed. install and distcheck are special and
# treated further below.
define recursive_rule_template
$(1) : $(foreach target,$(TARGETS),$(target).$(1)ed-stamp)
endef
define standard_rule_template
%.$(1)ed-stamp : %.source-change-stamp %.configured-stamp %.prerequisites-installed
make -j 4 -C $$* $(1) && touch $$@
endef
$(foreach rule,$(RULES),$(eval $(call recursive_rule_template,$(rule))))
$(foreach rule,$(filter-out install distcheck,$(RULES)),$(eval $(call standard_rule_template,$(rule))))
%.installed-stamp : %.alled-stamp
make -C $* install && touch $@
# This rule is probably the most complex. It collects option files named after a
# number of options and generates configure flags from them; this rule could be
# shortened considerably when you don't need project-specific configure/CFLAGS
# configuration.
%.configured-stamp : $(foreach i, all $(host_config) $(tag) $(host_config)-$(tag), global-$i.options) \
$(foreach i, all $(host_config) $(tag) $(host_config)-$(tag),%-$i.options) | %.prerequisites-installed
prefix="$(prefix)"; abs_builddir=$(abs_builddir); \
for i in $(filter %.options,$^); do . ./$$i; done; \
mkdir -p $* && cd $* \
&& echo "Configuring with $$OPTIONS CPPFLAGS=$$CPPFLAGS CFLAGS=$$CFLAGS CXXFLAGS=$$CXXFLAGS LDFLAGS=$$LDFLAGS PKG_CONFIG_PATH=$$PKG_CONFIG_PATH" INSTALL="$(INSTALL)" \
&& /bin/sh ../$(srcdir)/$*/configure --build=$(build_alias) --host=$(host_alias) --target=$(target_alias) --config-cache $$OPTIONS \
CPPFLAGS="$$CPPFLAGS" CFLAGS="$$CFLAGS" CXXFLAGS="$$CXXFLAGS" PKG_CONFIG_PATH="$$PKG_CONFIG_PATH" \
LDFLAGS="$$LDFLAGS" $(if $(CC),CC=$(CC),) $(if $(CXX),CXX=$(CXX),) \
INSTALL="$(INSTALL)"
touch $@
# The source change stamp is updated whenever a file in the source directory changes.
# It is used to prevent non-necessary sub-make invocations.
%.source-change-stamp : always-renew
{ test -e $@ && find $(srcdir)/$* -newer $@ -and -not -ipath '*/.svn*' -and -not -path '*/.libs*' | wc -l | grep -q '^0$$'; } \
|| touch $@
%.prerequisites-installed :
@true
%.distchecked-stamp : %.source-change-stamp %.configured-stamp %.prerequisites-installed
DISTCHECK_CONFIGURE_FLAGS=`./$*/config.status --config | sed -e "s/'--prefix=[^']*' //"` \
$(MAKE) -j 4 -C $* distcheck && touch $@
Makefile : $(srcdir)/Makefile.in config.status
./config.status $@
installcheck : dejagnu-tests-ran-stamp
dejagnu-tests-ran-stamp : $(foreach target,$(TARGETS),$(target).installed-stamp) testsuite.configured-stamp
make -C testsuite check
touch $@
always-renew :
@true
clean :
rm -rf *-stamp $(foreach target,$(TARGETS),$(target)/*.la $(target)/config.cache) deploy
realclean : clean
rm -rf $(TARGETS)
%.options :
touch $@
world : $(foreach target,$(TARGETS),$(foreach rule,$(RULES),$(target).$(rule)ed-stamp))
.PHONY : always-renew
.SECONDARY :
.DELETE_ON_ERROR :