【问题标题】:GNU make confused by code generatorGNU 被代码生成器弄糊涂了
【发布时间】:2011-09-18 09:24:39
【问题描述】:

我有一个代码生成器(生成 C++ 的 Python 脚本),它接受一个包含简单位图字体字形的文本文件,并生成带有字体参数和数据的 .h 和 .cc 文件。发电机的实际工作正常;它正在向 GNU make 解释这种安排,这给我带来了麻烦。

目录结构如下:

project_dir/
    app/
        Foo/
            Makefile
            ... application source files ...
            gcc/
                ... all object files ...
    lib/
        LCD/
            Font_ProFont_10.txt
            ... library source files ...

我的 make 规则如下所示:

Font_%.cc Font_%.h: Font_%.txt $(GENFONT)
    @if [ 'x${VERBOSE}' = x ]; then echo "FONT(F) $<"; else \
        echo $(GENFONT) $<; fi
    @$(GENFONT) $<

从一个干净的构建开始(这很重要),make 将在源代码上正常运行,直到它遇到一个字体,该字体会随着:

FONT(F) ../../lib/LCD/Font_ProFont_10.txt
  CXX   Font_ProFont_10.cc
arm-eabi-g++: Font_ProFont_10.cc: No such file or directory
arm-eabi-g++: no input files
make: *** [gcc/Font_ProFont_10.o] Error 1

重新运行make 将掩盖这个问题,因为make 会找到它真正所在的源文件:

  CXX   ../../lib/LCD/Font_ProFont_10.cc

由于在构建开始时Font_ProFont_10.cc 不存在,make 认为它将生成到当前目录 (project_dir/app/Foo/) 而不是库目录(这是规则所说的位置)会的,除非我遗漏了什么)。

我的关键问题是:如何更改 make 规则以使 make 不会混淆?

原则上我不想将生成的文件与分发的文件放在一起,但我也希望make 在一组干净的文件上成功完成。

我不想使用递归来执行此操作,因为需要将应用程序级别的配置传递给库。所以我将所有对象生成到应用程序目录中的一个目录中。

编辑:更改为以下内容:

VPATH += ../../lib/LCD
LCD = ../../lib/LCD
# ...
$(LCD)/Font_%.cc $(LCD)/Font_%.h: Font_%.txt $(GENFONT)
    # ...

没有解决问题:

make: *** No rule to make target `gcc/Font_Atmel_16.o', 
needed by `gcc/RTOSDemo.axf'.  Stop.

在这里,make 不知何故不知道您可以使用$(OBJDIR)/%.o: %.c 规则从../../lib/LCD/Font_Atmel_16.cc 生成gcc/Font_Atmel_16.o,因为../../lib/LCD$(VPATH) 中。它甚至不运行$(LCD)/Font_%.cc 规则。

【问题讨论】:

    标签: code-generation makefile


    【解决方案1】:

    问题在于您的Font_%.cc 规则并没有真正构建它声称构建的内容。如果 Make 尝试使用它来构建Font_ProFont_10.cc,它期望得到Font_ProFont_10.cc(并相应地计划),但它实际得到的是../../lib/LCD/Font_ProFont_10.cc。如果lib/LCD/ 是您想要生成的文件去的地方,那么这个

    ../../lib/LCD/Font_%.cc ../../lib/LCD/Font_%.h: Font_%.txt $(GENFONT)
        ...
    

    会做与你的旧规则完全相同的事情,但 Make 会知道会发生什么。请确保您的 %.o 规则在那里查找它们(以便它知道调用上述规则)。

    编辑:
    上述解决方案确实有效,但您必须确保%.o 规则在正确的位置查找生成的文件。在这种情况下,VPATH 是不够的。 如果您希望每个生成的文件与其源文件进入同一目录,并且 Make 知道它们在哪里用作先决条件 - 而您真的不想使用递归——我可以提出两种选择,既可行,又不完美:

    1. 当您在某处创建 Font_foo.cc 时,在 app/Foo/ 中创建指向它的符号链接,并在 Make 完成后删除该链接。 (没有必要为将来的 Make 调用保留链接,因为 VPATH 找到这些文件。)
    2. 创建与上述类似的定制规则,每个目录包含一个 %.txt 文件。 这可以通过 Make 自动完成, 小心使用“eval”和“call”。

    如果其中一种方法听起来合理,我可以更详细地列出它。

    【讨论】:

    • 当然,这意味着所有Font_%.txt 文件都需要位于一个目录中。所以我的问题变成了 有没有办法告诉make 产品将与输入位于同一目录中? 显而易见的$(&lt;D) 不起作用,而您的答案将起作用这种狭窄的情况(因为所有这些文件都在同一个目录中),它不适用于更一般的情况。 .o 规则将找到源,因为 ../../lib/LCD/$(VPATH) 中。 (如果有人想知道,%.cc %.h: %_font.txt $(GENFONT) 在重命名源后也不起作用;同样的错误。)
    • P.S.您的修复无效(见上文,已编辑问题)。也许.o 规则忽略了$(VPATH)
    • #2 和我在上面的编辑中尝试的有什么区别?这如何告诉%.o 规则在哪里寻找源?
    • 您的编辑不包含修改后的%.o 规则。我的选项 #2 涉及制定像 gcc/Font_%.o: ../../lib/LCD/Font_%.cc ... 这样的规则。
    • 整个%.o规则是否需要复制粘贴,或者有没有办法让$(OBJDIR)/Font_%.o: $(LCD)/Font_%.cc调用$(OBJDIR)/Font_%.o: %.cc
    猜你喜欢
    • 2017-07-24
    • 1970-01-01
    • 2022-01-23
    • 2019-01-12
    • 1970-01-01
    • 2014-08-14
    • 2016-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多