0

我有以下结构

home
|-- Makefile
|-- H1
|   |-- Makefile
|   `-- h1.c
|-- H2
|   |-- Makefile
|   `-- h2.c
|-- main.c

H1/生成文件

h1.o:h1.c
        gcc -c h1.c

H2/Makefile

h2.o:h2.c
        gcc -c h2.c

主页/Makefile

DIR = h1 h2
main.out:main.o
        for i in $(DIR);\
        do (cd $$i; make);\ //1.why () used here to encolose 2 commands and $$ before the i
        done
        gcc -o main.out main.o ./h1/h1.o ./h1/h1.o

main.o:main.c
        gcc -c main.c

以上工作正常并给我输出文件,但我怀疑这是进行此编译的有效方式或任何其他方式来执行此操作。

我的问题在代码的评论中被提及,并且也随之而来

I have tried like 
do(cd $i;make;)//this showing error
also do(cd $$i;)make;//this also sowing error

,请给我一些想法。这里发生了什么。我翻阅了一些书籍,发现 $$ 表示当前进程 ID ,但是在 i 之前这里有什么用。

还有什么是使用(), 来包含两个命令 [cdmake]。

请给我一些答案以解决我的疑问。

4

2 回答 2

1

1:正如@BasileStarynkevitch 所说,Make 扩展了这个:

for i in $(DIR); do (cd $$i; make); done

进入这个:

for i in h1 h2; do (cd $i; make); done

并将其传递给外壳。

2:括号不是必需的。这同样有效:

for i in $(DIR); do cd $$i; make; done

[正如 Virgile 指出的那样,我在这一点上是错误的。]

3:正如@BasileStarynkevitch 所说,$(MAKE) -C $$icd $$i; make.

4:您可以完全不使用循环(从而正确处理依赖关系):

h1/h1.o: h1/h1.c
    $(MAKE) -C h1

h2/h2.o: h2/h2.c
    $(MAKE) -C h2

main.out:main.o h1/h2.o h1/h2.o
    gcc -o main.out main.o ./h1/h1.o ./h2/h2.o

5:您可以完全不使用递归:

h1/h1.o: h1/h1.c
    gcc -c h1/h1.c -o h1/h1.o

h2/h2.o: h2/h2.c
    gcc -c h2/h2.c -o h2/h2.o

5:您可以使用自动变量来使您的规则更清晰:

h1/h1.o: h1/h1.c
    gcc -c $< -o $@

h2/h2.o: h2/h2.c
    gcc -c $< -o $@

main.out:main.o h1/h2.o h1/h2.o
    gcc -o $@ $^

您可以进一步简化,但对于这样一个简单的 makefile,它是不值得的。

于 2012-10-21T17:00:26.873 回答
1

make扩展规则操作中的所有生成变量(如$(CFLAGS)or $@),然后使用 shell 执行它。并$$展开为$。所以外壳会看到$i它的for循环内部。如果您只写$i在规则中,它会在调用 shell 之前(因为make没有任何绑定make-variable$(i) )被扩展(原样)为空。makei

使用GNU remakeremake -x以了解正在发生的事情。

顺便说一句,我相信你Makefile错了:(cd $$i; make)应该是$(MAKE) -C $$i (因为 GNU使进程非常特别$(MAKE),例如当你启动 a 时make -j 2

于 2012-10-21T16:14:58.947 回答