【问题标题】:Unix: Project Management with MakeUnix:使用 Make 进行项目管理
【发布时间】:2015-10-31 10:28:32
【问题描述】:

我的指示是:

制作这个程序的必要步骤是:

编译cpp2html.c生成cpp2html.o。 (重要提示:本项目源代码是C,不是C++,所以必须用gcc编译链接,而不是g++。)

运行命令

flex cppscanner.l 从 cppscanner.l 中的语言描述生成文件 lex.yy.c。

编译 lex.yy.c 以生成 lex.yy.o。 (这通常会产生有关额外令牌的警告消息。忽略它。)

链接 .o 文件以生成名为 cpp2html 的可执行程序

编写一个执行这些步骤的生成文件。当更改此过程的任何输入文件时,您的 makefile 应该只产生所需的最少步骤。 (注意:你可能无法像在作业的前面部分那样将这个 makefile 基于我的自我更新的 makefile。相反,你可能会发现有必要从头开始编写这个。

这是我的生成文件:

cpp2html: cpp2html.o lex.yy.o
        gcc -g -DDEBUG cpp2html.o lex.yy.o
        mv a.out cpp2html

lex.yy.o: lex.yy.c
        gcc -g -DDEBUG lex.yy.c

lex.yy.c:
        flex cppscanner.l

cpp2html.o: cpp2html.c
        gcc -g -DDEBUG cpp2html.c

我在这里做错了什么?我收到一条错误消息:

collect2:错误:ld 返回 1 个退出状态
make: *** [cpp2html.o] 错误 1

您的 makefile 在调用时不会生成“cpp2html”:
gcc -g -DDEBUG cpp2html.c

这是今晚到期,所以任何建议将不胜感激。

【问题讨论】:

  • 是您使用mv 而不是仅仅添加-o cpp2html 的原因吗?
  • 您的.c -> .o 规则不应该包含-c 参数吗?否则(正如我相信错误所暗示的那样),他们将尝试链接完整的可执行文件,而不是仅仅编译到目标文件。例如:gcc -c -g -DDEBUG cpp2html.c
  • 错误信息似乎不完整。 collect2: error: ld returned 1 exit status 之前有哪些行?
  • 这是来自CS 252 at Old Dominion Universitya coursework assignment。在阅读答案之前,请注意the Academic Honesty policy 非常清楚将他人的作品作为自己的作品提交的主题。 unix.meta.stackexchange.com/questions/4206

标签: c linux unix gcc makefile


【解决方案1】:

它抱怨以下内容:

cpp2html.o: cpp2html.c
        gcc -g -DDEBUG cpp2html.c

这一行正在尝试将cpp2html.c 编译为a.out

改成

cpp2html.o: cpp2html.c
        gcc -g -DDEBUG -c cpp2html.c

对将lex.yy.c 编译为lex.yy.o 的行执行相同的操作。 -c 选项告诉gcc 只生成目标文件并将其写入.o 文件。

您可以利用其他选项和一些内置变量。这是一个建议:

cpp2html: cpp2html.o lex.yy.o
        gcc -g -DDEBUG -o $@ $?

$@ 计算为目标的名称。 $? 评估为依赖项列表(.o 文件)。 -o 选项告诉gcc 将生成的二进制文件写入指定的文件名而不是a.out

您还可以利用隐式规则:

%.o : %.c
        gcc -g -DDEBUG -c $<

这会将任何.c 文件构建到相应的.o 文件中,因此您无需对cpp2html.clex.yy.c 重复相同的命令。

编辑

FWIW,这是我构建 makefile 的方式(带注释;假设 Gnu make):

# Variables used by implicit rules
CFLAGS=-g -DDEBUG -Wall -Werror  # flags for gcc
LFLAGS=                          # flags for flex, currently none
LEX=flex                         # lexer     
CC=gcc                           # C compiler

# Variables to make life easier
LSRCS=cppscanner.l                            # All of our flex source files
SRCS=cpp2html.c $(patsubst %.l,%.c,${LSRCS})  # All of our C source files
OBJS=$(patsubst %.c,%.o,${SRCS})              # All of our object files
TARGET=cpp2html                               # Final target name

${TARGET} : ${OBJS}              
        ${CC} ${CFLAGS} -o $@ $^ # Explicit rule to build target
                                 # $@ expands to target name
                                 # $^ expands to list of all prerequisites

clean:
        rm -rf *.o $(patsubst %.l,%.c,${LSRCS})

就是这样。我们依靠隐式 规则将.l 文件构建为.c 文件,并将.c 文件构建为.o 文件。隐式规则使用LEXCCLFLAGSCFLAGS 变量来运行带有正确选项的正确命令。我们只需要一个显式规则来构建我们的最终可执行文件。

像这样构建 makefile 的优点是您可以将文件添加到项目中,而无需添加新规则。

认为以上都是正确的;我的主机箱目前已关闭,因此我无法对其进行测试。详情请参阅Gnu Make manual

【讨论】:

  • 如果您要推荐宏,为什么不把${CC}${CFLAGS} 也加入?
  • @JonathanLeffler:两个原因 - 一是为了尽量减少信息过载,二是因为我在没有外接键盘的情况下使用 iPad 打字。
  • 谢谢大家!事实证明,makefile 是正确的,我只是在使用 flex 命令时遇到了问题。将目录中的所有文件移动到新目录中并从讲师目录中复制空白文件后,makefile 就起作用了。
猜你喜欢
  • 2010-12-09
  • 1970-01-01
  • 2010-12-30
  • 1970-01-01
  • 2010-11-16
  • 2016-01-16
  • 2016-05-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多