C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了为什么makefile坚持编译不应该编译的东西?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
所以我运行make lex并生成lex.yy.c文件,一切都很好

然后我运行make scAnner,它将一个名为scAnner.c的源文件转换为编译,它应该只运行cc lex.yy.c scAnner.c -o scAnner,但它会这样做:

lex  -t scAnner.l > scAnner.c
cc lex.yy.c scAnner.c -o scAnner

为什么它决定运行lex -t scAnner.l并将其输出到scAnner.c有效地覆盖我的代码?没有该死的想法,这让我发疯了.

我的makefile:

scAnner: scAnner.h scAnner.c lex.yy.c
    cc lex.yy.c scAnner.c -o scAnner 

lex: scAnner.l
    lex scAnner.l > lex.yy.c

clean:
    rm lex.yy.c
    rm scAnner

出了什么问题?

解决方法

每当发生这种情况时,您在构建目录中都有一个scAnner.c
扫描仪.l比scAnner.c更新

当您运行make scAnner时,配方:

scAnner: scAnner.h scAnner.c lex.yy.c
    cc lex.yy.c scAnner.c -o scAnner

要求其先决条件scan.c应为uptodate.您
没有提供这样做的配方,所以要回落
在其内置食谱数据库.

通过运行make -p来检查那些内置的配方,你会发现:

%.c: %.l
#  recipe to execute (built-in):
    @$(RM) $@ 
     $(LEX.l) $< > $@

这个内置配方将通过运行以下命令从匹配的file.l生成file.c:

rm file.c   # Not echoed
lex  -t file.l > file.c
@H_589_2@make发现此配方的模式规则 – %.c:%.l – 已满足
通过scAnner.c,因为ScAnner.l存在,并且比scAnner.c更新.
所以它使用这个配方来使scan.c uptodate:

lex  -t scAnner.l > scAnner.c

从而破坏了你的扫描仪.

如果你不想让make永远地应用这个内置配方,你可以明确地
通过只写规则取消它:

%.c: %.l

在没有任何配方的makefile中.

您还可以通过传递–no-builTin-rules来禁用所有内置配方
制作命令行.

但是,每当你对makefile的行为有所期望
被内置食谱破坏它强烈表明你的期望
对于从输入文件制作输出文件的常用方法,他们并不了解情况
使用makefile调用的工具.
制作Catalogue of Built-In Rules

%.<target-type>: %.<prereq-type>
    <command>
    ...

体现了制作< target-type>的规范方式来自< prereq-type>的文件@H_382_19@make文件,这样你就不必自己写这个食谱了
你的文件.例如,能够胜任GNU make的C和C程序员
不要编写从.c文件或.cpp文件制作.o文件的配方,除了
极端情况,因为他们知道make的方式会自动完成
通常是他们想要的方式.

@H_589_2@make的内置配方为%.c:%.l规则表达了规范的方式
在给出file.l的情况下制作file.c所以问问自己:如果你不想要scAnner.c
要像scan.l那样制作,如果你想要lex.yy.c
可以从scAnner.l制作,对你调用文件是必要的还是有用的
scan.l被调用,当你还有一个非常独立的源文件
叫scan.c?

假设你在这个玩具示例中利用了make的内置配方:

lexer.l

%{
#include <stdio.h>
%}
%%
[ \t] ;
[0-9]+\.[0-9]+ { printf("Found a floaTing-point number: [%s]\n",yytext); }
[0-9]+  { printf("Found an Integer: [%s]\n",yytext); }
[a-zA-Z0-9]+ { printf("Found a String: [%s]\n",yytext); }
%%

scAnner.c

#include "scAnner.h"

int main(void) {
    yylex();
    return 0;
}

scAnner.h

#ifndef SCAnnER_H
#define SCAnnER_H

extern int yylex(void);

#endif

然后你的makefile可能只是:

@H_589_2@makefile文件

SRCS := scAnner.c lexer.c
OBJS := $(SRCS:.c=.o)
LDLIBS := -lfl

.PHONY: all clean

all: scAnner

scAnner: $(OBJS)
    $(LINK.o) -o $@ $^ $(LDLIBS)

scAnner.o: scAnner.h

clean:
    rm -f scAnner *.o

运行方式如下:

$make
cc    -c -o scAnner.o scAnner.c
lex  -t lexer.l > lexer.c
cc    -c -o lexer.o lexer.c
cc   -o scAnner scAnner.o lexer.o -lfl
rm lexer.c

请注意,make运行所有这些命令:

cc    -c -o scAnner.o scAnner.c
    lex  -t lexer.l > lexer.c
    cc    -c -o lexer.o lexer.c

没有你的lexer.c,lexer.o和scAnner.o
写下任何告诉它如何做的食谱.它也是自动
通知lexer.c是一个中间文件生成文件
只需要存在从lexer.l到lexer.o – 所以它删除
它在最后:

rm lexer.c

没有被告知.

这个扫描仪运行如下:

$./scAnner 
Hello
Found a String: [Hello]

42
Found an Integer: [42]

42.42
Found a floaTing-point number: [42.42]

^C

大佬总结

以上是大佬教程为你收集整理的为什么makefile坚持编译不应该编译的东西?全部内容,希望文章能够帮你解决为什么makefile坚持编译不应该编译的东西?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。