【问题标题】:Iterating directories and conditions in makefiles在 makefile 中迭代目录和条件
【发布时间】:2016-10-17 09:21:09
【问题描述】:

我有一个存储库结构,其中依赖关系可以是 svn:external'd 或者在这个存储库中,也可以在具有 svn:external'd 这个的超级存储库中。外部只有一层深,因此如果我的存储库被超级存储库外部化,那么我需要能够检测到在哪里可以找到更高级别的依赖项,并复制所有相关数据。如果确实在我自己的存储库中找到了依赖项,那么我需要构建它。

我在创建我的 makefile 配方来执行此操作时遇到问题。这是我到目前为止所拥有的:

DEPENDENCIES = dep1 dep2
ROOTDIR = .

deps : 
    for dep in $(DEPENDENCIES); do \
        if [ -e $(ROOTDIR)/ext/$$dep ]; then \
            depdir = $(ROOTDIR)/ext/$$dep; \
            $(MAKE) -C $depdir; \
        elif [ -e $(ROOTDIR)/../$$dep ]; then \
            depdir = $(ROOTDIR)/../$$dep; \
        else \
            $(error Could not find dependency: $$dep) \
        fi \
        cp $$depdir/bin/* $(ROOTDIR)/bin; \
        cp $$depdir/lib/* $(ROOTDIR)/lib; \
        cp $$depdir/inc/$$dep $(ROOTDIR)/inc/$$dep; \
    done

第一个问题是 $(error) 行。我希望能够抛出错误,但这显然不受 bash 条件语句的影响。这是输出:

$ make deps
makefile:108: *** Could not find dependency: $dep.  Stop.

如果我注释掉那个 else 语句,那么我仍然有麻烦

$ make deps
for dep in dep1 dep2; do \
        if [ -e ./ext/$dep ]; then \
/bin/sh: -c: line 2: syntax error: unexpected end of file
make: *** [makefile:106: deps] Error 1

有人可以提供一些有关如何完成此操作的提示吗?我在 cygwin 和 linux 环境中都运行 GNU make。

编辑:我真的希望尽可能地保持这种状态(以及尽可能少的外壳材料)。我想我已经接近了一点,但仍然需要对 $(DEPENDENCIES) 中的每个项目重复此操作。

DEPENDENCIES = foo bar
ROOTDIR = .
EXTDIR = $(ROOTDIR)/ext
BINDIR = $(ROOTDIR)/bin
INCDIR = $(ROOTDIR)/inc

# Need a foreach DEP in $(DEPENDENCIES) here
ifneq("$(wildcard $(EXTDIR)/$(DEP))","")  
DEPDIR = $(EXTDIR)/$(DEP)
BUILDDEP = $(MAKE) -C $(DEPDIR)/build
else ifneq("$(wildcard $(ROOTDIR)../$(dep))", "") 
DEPDIR = $(ROOTDIR)/../$(dep)
else
$(error Could not find dependency: $(DEP))
endif 

$(DEPDIR) :
    $(BUILDDEP)
    cp $(DEPDIR)/bin/* $(BINDIR)
    cp $(DEPDIR)/inc/$(DEP)/* $(INCDIR)/$(DEP)

编辑2: 我想我越来越近了。以下看起来更像我想要的,但它仍然有问题: 1)我不知道如何调用每个食谱 2)如果没有找到所有依赖项,它不会给出错误 3)它不允许我决定构建顺序 4)它不允许我过滤以仅使用依赖项中列出的文件夹(它会处理所有文件夹)

ifneq "$(wildcard $(EXTDIR)/%/build)" ""  
$(EXTDIR)/%:
    $(MAKE) -C $(EXTDIR)/%/build
    cp $(EXTDIR)/%/bin/* $(BINDIR)
    cp $(EXTDIR)/%/int/*.a $(INTDIR)
    cp $(EXTDIR)/%/inc/%/* $(INCDIR)/%
endif

ifneq "$(wildcard $(ROOTDIR)/../%/build)" ""
DEPDIR = $(ROOTDIR)/..
$(DEPDIR)/%: 
    cp $(DEPDIR)/%/bin/* $(BINDIR)
    cp $(DEPDIR)/%/int/*.a $(INTDIR)
    cp $(DEPDIR)/%/inc/%/* $(INCDIR)/%
endif

编辑3 在被告知我试图一次解决太多问题后,我将其简化为:

DEPENDENCIES = dep1 dep2 dep3

for each DEP in $(DEPENDENCIES)

$(DEP) : 
    $(MAKE) -C ../ext/$(DEP)

如何为 $(DEPENDENCIES) 中的每个项目创建一个配方 ($(DEP) )?

【问题讨论】:

  • 您正在编写一个 shell 脚本,而不是 Makefile:那里没有规则。把它变成一个shell脚本!
  • 您试图一次解决太多问题。尝试从命令行执行此操作(即不使用 Make),如果您对其中的一部分有问题,请将该问题归结为核心(例如,如何在 bash 中抛出错误?),如果您无法解决这个问题,在这里问。
  • 从命令行执行此操作对我来说很容易。但是,我更喜欢使用 make 以便: A) 这个框架可以被通用化并且易于配置以供其他开发人员使用 B) 我不被 g++ 和 Linux 所束缚。我们还想在 Windows 中使用 MinGW 进行开发,因此 Bash 对我来说不是一种好用的语言。
  • 您的解决方案也是并行安全的。将-j5(比如说)给makemake 将确保您的CPU 在所有子make 中保持忙碌。好的。注意事项:您可能需要添加 .PHONY: ${DEPENDENCIES} 以将它们标记为符号目标,否则如果有人创建了一个名为 ../ext/dep2 的文件(比如),它将出现异常。

标签: makefile gnu-make


【解决方案1】:

解决了。这样就解决了上面的问题:

DEPENDENCIES = dep1 dep2 dep3
$(DEPENDENCIES) : 
    $(MAKE) -C ../ext/$@

答案很简单。我希望我对这些东西有足够的了解,以便提出一个更清晰的问题。

【讨论】:

    猜你喜欢
    • 2012-11-06
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    • 1970-01-01
    • 2019-04-27
    • 1970-01-01
    相关资源
    最近更新 更多