在 makefile 中迭代目录和条件
Iterating directories and conditions in makefiles
我有一个存储库结构,其中依赖关系可以在这个存储库中 svn:external'' 或在具有 svn:external' 这个的超级存储库中。外部只有一层深,所以如果我的 repo 被超级存储库外部化,那么我需要能够检测到在哪里可以找到更高级别的依赖项,并复制所有相关数据。如果确实在我自己的仓库中找到依赖项,那么我需要构建它。
我在创建 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。
编辑:我真的更愿意让它尽可能接近制作(并且尽可能少 shell 东西)。我想我已经接近了一点,但仍然需要对 $(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) )?
已解决。这解决了上面的问题:
DEPENDENCIES = dep1 dep2 dep3
$(DEPENDENCIES) :
$(MAKE) -C ../ext/$@
答案很简单。我希望我对这些东西有足够的了解,以便提出一个更清晰的问题。
我有一个存储库结构,其中依赖关系可以在这个存储库中 svn:external'' 或在具有 svn:external' 这个的超级存储库中。外部只有一层深,所以如果我的 repo 被超级存储库外部化,那么我需要能够检测到在哪里可以找到更高级别的依赖项,并复制所有相关数据。如果确实在我自己的仓库中找到依赖项,那么我需要构建它。
我在创建 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。
编辑:我真的更愿意让它尽可能接近制作(并且尽可能少 shell 东西)。我想我已经接近了一点,但仍然需要对 $(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) )?
已解决。这解决了上面的问题:
DEPENDENCIES = dep1 dep2 dep3
$(DEPENDENCIES) :
$(MAKE) -C ../ext/$@
答案很简单。我希望我对这些东西有足够的了解,以便提出一个更清晰的问题。