为啥我的 makefile 调用 gcc 虽然我设置了 CC=g++? [关闭]
Posted
技术标签:
【中文标题】为啥我的 makefile 调用 gcc 虽然我设置了 CC=g++? [关闭]【英文标题】:Why does my makefile call gcc although I set CC=g++? [closed]为什么我的 makefile 调用 gcc 虽然我设置了 CC=g++? [关闭] 【发布时间】:2017-05-23 17:25:09 【问题描述】:我有一个与g++ -std=c++17 -Wall -Og -g -o main *.cc
完美编译的小代码。现在我想要一个makefile,到目前为止我得到了这个:
CC = g++
CFLAGS = -Wall -std=c++17 -Og -g
DEPS = random_tools.h
OBJ = main.o random_tools.o
%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -o $@ $<
main: $(OBJ)
gcc $(CFLAGS) -o $@ $^
但是,当我运行 make
时它崩溃了,告诉我
g++ -c -o main.o main.cc
g++ -c -o random_tools.o random_tools.cc
gcc -Wall -o main main.o random_tools.o
main.o: In function `main':
main.cc:(.text+0x1d): undefined reference to `std::cout'
main.cc:(.text+0x22): undefined reference to `std::ostream::operator<<(int)'
main.cc:(.text+0x27): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
main.cc:(.text+0x2f): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
main.o: In function `__static_initialization_and_destruction_0(int, int)':
main.cc:(.text+0x5d): undefined reference to `std::ios_base::Init::Init()'
main.cc:(.text+0x6c): undefined reference to `std::ios_base::Init::~Init()'
collect2: error: ld returned 1 exit status
make: *** [makefile:10: main] Error 1
我真的不明白为什么它使用gcc
而不是g++
- 我告诉它使用g++
。有人可以阐明这里发生的事情以及我如何让make
照我说的去做吗?谢谢。
【问题讨论】:
因为您在链接器命令中明确使用它:gcc $(CFLAGS) -o $@ $^
?
请注意,CC
通常被认为是 C 编译器,而不是 C++ 编译器。 C++ 编译器的正常变量是CXX
和CXXFLAGS
。
将通常与 C 相关联的 make 变量用于 C++ 是个坏主意。给 C++ 源文件添加 .c 后缀也是一个坏主意。
@Barmar 感谢您的提示。它只是一个命名约定还是会触发不同的行为?
这是默认规则使用的命名约定。
【参考方案1】:
这条规则
main: $(OBJ)
gcc $(CFLAGS) -o $@ $^
已将“gcc”硬连线到其中。将其更改为$(CC)
,它将按您的预期运行。
也就是说,最好像这样编写这个 Makefile:
CXX = g++
CXXFLAGS = -Wall -std=c++17 -Og -g
DEPS = random_tools.h
OBJ = main.o random_tools.o
# Default goal
main: $(OBJ)
$(LINK.cc) $^ -o $@ $(LDLIBS)
# Header dependencies
$(OBJ): $(DEPS)
这使用了内置的 Make 约定,因此以后扩展起来会容易得多。 (我没有篇幅在这里解释所有内置的 Make 约定。我建议您阅读 GNU Make manual 封面。)
(请注意,如果您实际上将源文件命名为 main.c
和 random_tools.c
而不是 main.cc
和 random_tools.cc
,这将不会达到您的预期。但您应该使用 @987654329 @ 用于 C++ 源文件。)
【讨论】:
您应该在链接器命令中考虑LDLIBS
和LDFLAGS
;使用$(LINK.cc) $(OUTPUT_OPTION) $^
- 或$(LINK.cc) -o $@ $^
最容易做到这一点 - 请参阅其他答案。
@TobySpeight 答案已更正,但请注意,除了我之前所说的 OUTPUT_OPTION 之外,LDLIBS 不 包含在 LINK.cc 中,因为 -l 选项需要最后死掉在命令行上。
TBH,当我需要这样的规则时,我运行make --print-data-base
并复制/粘贴——这是我在评论时应该做的!
@TobySpeight 这是一个好习惯,我这样做是为了提醒自己$(LINK.cc)
扩展为什么。但在这种情况下,它可能会让你误入歧途,因为默认链接规则中有 $(LOADLIBES)
,我不得不在手册中查找它以了解它是 $(LDLIBS)
的过时替代名称,为了向后兼容而保留,并且不需要复制到新的 Makefile 中。【参考方案2】:
您在 Makefile 的 main
部分(第 9 行)中使用了 gcc 命令。您应该将其替换为:$(CC) $(CFLAGS) -o $@ $^
【讨论】:
更好的是,替换为$(LINK.cc) $(OUTPUT_OPTION) $^
,这样LDLIBS
等等就可以轻松工作。
@TobySpeight $(OUTPUT_OPTION) 不应在链接规则中使用,因为在某些情况下它会扩展为 ; mv -f $(<F).o $@
,这显然在链接规则中不起作用。
真的 - 这是怎么回事?它应该始终扩展到-o $@
AFAICT。
@TobySpeight 当 Make 认为编译器不支持 -o
和 -c
时会发生这种情况,这在当今非常罕见,但并非完全不可能。我不记得 Make 如何决定编译器是否支持-o
和-c
。
在这种情况下,$(LINK.cc) -o $@ $^
。我坐得更正了。以上是关于为啥我的 makefile 调用 gcc 虽然我设置了 CC=g++? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
Emscripten - 如何将我的makefile与emcc一起使用而不是gcc?
你如何为 clang 和 gcc 编写一个 makefile?
gcc makefile错误:“没有规则来制作目标......”