【问题标题】:Calling flex from a makefile从 makefile 调用 flex
【发布时间】:2012-03-19 12:25:44
【问题描述】:

我想调用 flex 来构建一个 .l 文件,然后调用 gcc 来构建一切。

我试过了:

comp:
    lex scanner.l   \
    gcc -o a.out main.c hash.c -I.  

错误:

lex scanner.l   \
    gcc -o a.out main.c hash.c -I.  
lex: impossible to opne gcc
/usr/bin/m4:stdin:2994: ERROR: end of file in string

lex scanner.l
<tab> gcc -o a.out main.c hash.c -I.

错误:缺少分隔符。

lex 生成的 lex.yy.c 已包含在主文件中。

提前致谢,

佩德罗

【问题讨论】:

  • 在第二个示例中,both 命令之前需要制表符。
  • @Pedro Dusso - 为了方便起见,您是否将 lex.yy.c 包含到 main.c 中,即避免编写外部声明或其他原因。 lex.yy.c 文件不必包含在 main.c 中
  • @gbulmer:是的,我注意到了。但是,我在scanner.lc 部分定义了一个initMe() 函数。我的 main.c 将被一个通用的自动化测试所取代。如何在scanner.l 中包含main.c?只需添加正确的包含并重新制作?
  • @gbulmer:是的,我只需要重新排序编译顺序并修复包含。非常感谢您的帮助!

标签: c gcc makefile lex


【解决方案1】:

试试这个:

lex.yy.c: scanner.l
    lex scanner.l

comp: main.c hash.c
    gcc -o a.out main.c hash.c -I.

main.c: lex.yy.c

第一个规则集告诉make lex.yy.c 需要在任何时候重建 scanner.l 并提供重建命令 lex.yy.c。第二个规则集告诉make,虚假目标 comp 依赖于 main.chash.c。如果任一文件发生更改,则调用 make comp 将导致重新编译。最后一行是一个独立的依赖项,它告诉make 在任何 lex.yy.c 更改时将 main.c 视为脏。如果 lex.yy.c 不存在,它还将强制调用 make comp 来创建它。

【讨论】:

  • 我认为最后一行 main.c: lex.yy.c 可能不正确; main.c 通常不包含 lex.yy.c。您是否在考虑有时包含在 main.c 中的 y.tab.h 文件?
  • 我认为使用规则comp: main.c hash.c 没有优势(在这种情况下)。相反,规则可以使程序 a.out 依赖于所有来源。
  • @perreal - 我不认为它必须是,请参阅GNU flex document "flex 默认生成一个 C 源文件 lex.yy.c 作为输出,它定义了一个例程 yylex() . 这个文件可以编译并与 flex 运行时库链接以生成可执行文件。” main 只需要调用 yylex()。
  • @D.Shawley:非常感谢您提供如此详细的信息。我仍然不确定一件事:当我在这里测试时,我的 a.out 没有更新。然后我更改了scanner.l 以强制更新,但仍然没有。我应该更改什么以使其生成 a.out 可执行文件?我真的不需要“comp”的东西,那只是我的尝试:P
  • @perrea - 我很抱歉,我的错误。我会问 OP 为什么他们将 ley.yy.c 包含到 main.c 中
【解决方案2】:
all: a.out

lex.yy.c: scanner.l
    lex scanner.l

a.out: lex.yy.c main.c hash.c
    gcc -o a.out main.c hash.c -I.  

【讨论】:

  • 对不起,我们越界了。如果您不介意,我会留下我的,因为您的答案不完整。 lex.yy.c 需要在某个阶段编译
【解决方案3】:

删除反斜杠,或在其前添加分号 (;)。
就像现在一样,这两个命令在一行中相加,并作为一个长命令执行。

【讨论】:

    【解决方案4】:

    IIRC 通常的 Makefle 模式是

    a.out: lex.yy.c main.c hash,c
    <tab> gcc -o a.out main.c hash.c lex.yy.c -I. -ll
    
    lex.yy.c: scanner.l
    <tab> lex scanner.l
    

    这是错误的,因为在原始代码中,main.c 包含了 lex.yy.c

    这假设原始代码已更改,因此 main.c 包含 lex.yy.c

    如果不进行该更改,这将失败,因为 yylex() 将有两个定义,一个来自 main.c 中的 #include,另一个是作为源代码编译单元提供的。我鼓励人们不要将 .c 文件包含到另一个 .c 文件中。

    一般来说,惯例是对包含的源文件使用不同的文件扩展名 (.i),这些文件会生成唯一的符号和代码。

    【讨论】:

    • 我认为这会导致错误,当 gcc 尝试链接 mainlex.yy 时,它们包含相同函数的不同定义。
    • @Beta - 你是对的,如果 lex.yy.c 包含在 main.c 中,它将有两个 yylex 定义。我总是避免包含 lex.yy.c,并且总是只编译和链接它。我使用共享头文件来定义类型、函数和共享数据。我喜欢这种方法,因为随着程序的发展,我可能想将源代码重构为新文件。所以我发现有明确的标题来定义共享符号的好处。我希望发现为什么 OP 将 lex.yy.c 包含到 main.c 中。 TBF,如果问题很小,那几乎没有关系,但我的“反应”帮助了我,所以我想理解。
    • 我有同样的直觉,我认为 OP 应该采用它,我只是指出为什么你的解决方案可能不适合他所写的;一次一个障碍。
    • @Beta - 这会改善我的答案吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-16
    • 2019-11-12
    • 1970-01-01
    相关资源
    最近更新 更多