如何避免使用类似的配方在Makefile目标中重复?

时间:2016-06-12 18:13:45

标签: makefile dry

我有一个包含很多目标的Makefile,每个目标的配方非常相似。

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

我想避免所有这些重复。我想有类似下面的内容(这不是有效的语法;这只表达了我的意图)。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Text;

namespace Resources
{
 public class ResManager
 {

    public static void SoundCopy(String ResourceName, String Dest)
    {
        try
        {
            var rm = Resources.Sounds.ResourceManager;
            var resStream = rm.GetStream(ResourceName);

            if (!File.Exists(Dest))
            {
                File.Create(Dest).Close();
            }
            FileStream fs = new FileStream(Dest, FileMode.OpenOrCreate);

            CopyStream(resStream, fs);

            resStream.Close();
            resStream = null;

            fs.Close();
            fs = null;

            rm.ReleaseAllResources();
            rm = null;

        }
        catch (Exception e)
        {
            // nothlng
        }

    } // S copy();

    private static void CopyStream(Stream from, Stream to)
    {
        int bufSize = 1024, count;
        byte[] buffer = new byte[bufSize];
        count = from.Read(buffer, 0, bufSize);
        while (count > 0)
        {
           // StackOverflow -- working set raises here
            to.Write(buffer, 0, count);
            count = from.Read(buffer, 0, bufSize);
        } 

        // clean up
        buffer = null;
    } // c str()


 } //class
} //namespace

有可能做这样的事吗?如果没有,我可以写的最好的Makefile是什么,可以减少食谱中的重复?

2 个答案:

答案 0 :(得分: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 $@

(感谢Beta指出我原来的想法)

答案 1 :(得分:2)

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

foo bar baz:
    gcc $@.c -o $@
    mv $@ ~/bin

但是,您应该在规则中明确依赖关系:

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

foo bar baz:
    gcc $< -o $@
    mv $@ ~/bin

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