【问题标题】:automake and project dependenciesautomake 和项目依赖
【发布时间】:2012-01-03 05:02:11
【问题描述】:

我有一个想要使用 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)

我对 automake 比较陌生,但我(几乎)知道如何使用它来成功构建单个项目。

我想要一个“主”项目文件(如果可能的话),它指定项目模块的构建顺序、运行单元测试并在以下情况下使整个构建过程失败:

  • 其中一个模块无法构建
  • 其中一个模块未能通过单元测试

我将如何编写这样一个“主项目”文件(或调用任何其他机制)来构建具有大量模块间依赖关系的项目?

【问题讨论】:

    标签: c++ c makefile automake


    【解决方案1】:

    如果您使用的是 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 提供了参考文档 - 但它是一个糟糕的教程。我遇到的最好的指南之一可以在 here 找到。

    【讨论】:

    • 在这种情况下,Makefile/automake 部分可能不是主要问题(即使我同意 automake),因为模块 4 的配置运行已经失败(模块 1 尚未安装,因此不可配置)。
    • @thiton,libtool 应该透明地处理这个问题。
    • 很公平,没有意识到您没有通过 autoconf 检查任何库依赖项,而是完全依赖于 libtool。但是,它会阻止任何子包的分发,不是吗?
    • 不,但希望能推翻我的一大堆废话。对不起,如果这听起来像是不合理的批评。我已经对你的帖子投了赞成票。如果你确实解决了这个问题,我很想知道你是如何解决子目录库存在的配置时检查的。
    • @BrettHale 我更喜欢你的方法。顺便说一句,我指的是 Automake(不是 autotools)。我已经更新了我的问题以反映这一点。你能指出我在哪里可以找到关于你建议的方法更详细的文档吗?
    【解决方案2】:

    encountered the same issue 发现纯自动工具解决方案很难运行,因为配置脚本例如对于module4,依赖于module1的安装。

    针对这种情况的手动生成文件和配置脚本相当容易生成。我已经粘贴在 rapidSTORM 项目 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 :
    

    【讨论】:

    • 能否请您注释该代码,以便我们了解所有不同部分对实现目标的贡献?
    • @RobKennedy:我想,但我不确定我是否能找到时间。请随时编辑,并提出任何具体问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    • 2019-11-15
    • 1970-01-01
    • 2011-04-29
    相关资源
    最近更新 更多