食谱在第一个目标之前开始 [英] recipe commences before first target

查看:289
本文介绍了食谱在第一个目标之前开始的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

错误:Makefile:12:***配方在第一个目标之前开始.停止.

Error : Makefile:12: *** recipe commences before first target. Stop.

我的makefile:

My makefile:

objDir := obj
incDir := include
srcDir := src
binDir := bin
files := matrix palindrome encryption

define generateObject
    @nasm -f elf32 -o $(objDir)/$(1).o $(srcDir)/$(1).asm
endef

object: $(addprefix $(srcDir)/,$(addsuffix .asm,$(files)))
    @echo -n "Generating object files... "
    $(foreach file,$(files),$(eval $(call generateObject,$(file))))
    @echo "Done"

我在一篇帖子中读到,这可能是由于不需要的空格/制表符引起的,但我找不到任何内容.

I read in a post that this could be due to unwanted whitespace/tab but i could not find any.

我尝试了cat -e -t -v Makefile,输出为:

objDir := obj$
incDir := include$
srcDir := src$
binDir := bin$
files := matrix palindrome encryption$
$
define generateObject$
^I@nasm -f elf32 -o $(objDir)/$(1).o $(srcDir)/$(1).asm$
endef$
$
object: $(addprefix $(srcDir)/,$(addsuffix .asm,$(files)))$
^I@echo -n "Generating object files... "$
^I$(foreach file,$(files),$(eval $(call generateObject,$(file))))$
^I@echo "Done"$

推荐答案

您的问题是使用eval函数. eval用于解析 make 构造,但是您正在向它传递一个shell命令.考虑这一行:

Your problem is use of the eval function. eval is used to parse make constructs, but you're passing it a shell command. Consider this line:

$(foreach file,$(files),$(eval $(call generateObject,$(file))))

每次在列表中都将使用文件名调用generateObject.那将扩展为一个shell命令.例如,如果file矩阵,则call将扩展为:

Each time through the list you'll call generateObject with a filename. That will expand to a shell command; for example if file is matrix then call will expand to:

^I@nasm -f elf32 -o obj/matrix.o src/matrix.asm

然后,您将该文本字符串传递给eval,后者尝试将其读取为makefile.请注意,传递给eval的文本本身必须是完整且有效的makefile;就像您递归调用make并将此字符串作为makefile一样,只是将解析结果应用于当前的makefile.您不能只给eval一个有效的makefile文件的一部分(如配方中的一个命令行),并将其插入到当前的makefile文件中.由于该行本身无效,因此会出现此错误.

Then you take that text string and pass it to eval which tries to read that as a makefile. Note that the text passed to eval must be a complete and valid makefile in itself; it's like you invoked make recursively and gave it this string as a makefile, except that the result of parsing are applied to the current makefile. You can't give eval just a part of a valid makefile (like one command line in a recipe) and have it insert that into the current makefile. Because that line by itself isn't valid, you get this error.

您希望将结果连接到一个shell命令中,而不是对结果运行eval.试试这个:

Instead of running eval on the results you want to concatenate them into one shell command. Try this:

define generateObject
  nasm -f elf32 -o $(objDir)/$(1).o $(srcDir)/$(1).asm
endef

object: $(addprefix $(srcDir)/,$(addsuffix .asm,$(files)))
        @echo -n "Generating object files... "
        @$(foreach file,$(files),$(call generateObject,$(file)) && ) true
        @echo "Done"

但是,那真的不是让路".您不想在一条规则内建立多个目标:这违反了make的要点,即make只能重建过期的文件.

However, that's really not "the make way". You don't want to build multiple targets within a single rule: that defeats the main point of make which is that it only rebuilds the files that are out of date.

您应该这样编写makefile:

You should write your makefile like this:

object: $(files:%=$(objDir)/%.o)

$(objDir)/%.o : $(srcDir)/%.asm
        @nasm -f elf32 -o $@ $<

您不需要generateObject变量,calleval甚至foreach.

You don't need the generateObject variable, or call, or eval, or even foreach.

这篇关于食谱在第一个目标之前开始的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆