2016-06-12 61 views
1

我有一个Makefile,它有很多目标,每个目标的配方都很相似。如何避免使用类似食谱的Makefile目标中的重复?

foo: 
    gcc foo.c -o foo 
    mv foo ~/bin 

bar: 
    gcc bar.c -o bar 
    mv bar ~/bin 

baz: 
    gcc baz.c -o baz 
    mv baz ~/bin 

我想避免所有这些重复。我想要下面的东西(这不是有效的语法;这只表达我的意图)。

TARGET_NAME: 
    gcc $(TARGET_NAME).c -o $(TARGET_NAME) 
    mv $(TARGET_NAME) ~/bin 

是否可以这样做?如果不是,我可以写的最好的Makefile是什么,可以最大限度地减少食谱中的重复?

+0

像@beta已经在其他地方指出的那样,你的'Makefile'坏了,因为你移动了你创建的文件,所以每次都会重新映射它们,无论它是否必要。此外,'go'的'-o'选项可以显着地占据一个子目录。 'bin /%:%.c; gcc $ <-o $ @' – tripleee

回答

4

你的Makefile是错误的,因为你的目标(foobar等)不依赖于它们的源文件(foo不依赖于foo.c等)所以,改变源代码将不会导致目标被重建。

此外,你的makefile文件说你正在创建一个文件foo,但是你的配方实际上创建了一个文件~/bin/foo,这不是一回事。

无论如何,这正是pattern rules是:

EXES = foo bar baz 

all: $(addprefix $(HOME)/bin/,$(EXES)) 

$(HOME)/bin/%:: %.c 
     gcc $< -o [email protected] 

(感谢测试版指出在原来的我想到-O)

+2

你不是在违反[你自己的规则](http://make.mad-scientist.net/papers/rules-of-makefiles/)吗? 6中的第2个,准确地说:目标模式应该与正在构建的事物的实际名称相匹配('〜/ bin /%')。 – Beta

+0

您应该使用[静态模式规则](https://www.gnu.org/software/make/manual/html_node/Static-Usage.html)以避免使用[隐式规则](https://www.gnu。组织/软件/制作/手动/ html_node /静态抗Implicit.html)。像这样的东西:'foo bar baz:%:%.c' – jml

+0

你说得对。我认为这是一个“cp”而不是“mv”。我会更新。关于“静态模式规则”:我总是看到你“应该”使用它们的建议。我几乎从不使用它们。实际上,我总是使用正常的模式规则,并且只有在使用静态模式规则时,才有了应该以不同方式构建的目标子集。我认为这是一种风格/意见。我不会告诉人们他们“应该”在没有任何正当理由的情况下使用他们。 – MadScientist

2

一个make规则实际上可以匹配多个目标:

foo bar baz: 
    gcc [email protected] -o [email protected] 
    mv [email protected] ~/bin 

然而,你应该作出明确的依赖关系的规则:

foo: foo.c 
bar: bar.c 
baz: baz.c 

foo bar baz: 
    gcc $< -o [email protected] 
    mv [email protected] ~/bin 

前三行只是指定依赖项,而没有任何操作来实际构建它们。您可以在gcc的帮助下生成这些文件:gcc -MM foo.c将打印foo.c的规则。