【问题标题】:Makefile: undefined reference to 'std::...'Makefile:未定义的对 'std::...' 的引用
【发布时间】:2017-04-08 03:30:12
【问题描述】:

我没有 Unix 经验,而且 C++ 经验非常有限。我最近被分配了一个编码项目,该项目要求我们提供 C++ 源代码以及 makefile。

教授提供了一个示例makefile,并提到我们应该完全遵循它的格式。我试图让它适用于单个文件“main.cpp”,下载MinGW和Cygwin后,我可以从终端编译和运行良好。但是,尝试运行 makefile 会导致一堆“未定义的对...的引用”错误。

makefile 是:(我改变的只是项目和目标文件的名称)

VPATH = ./src:

.SUFFIXES : .F90 .f .f90 .c .o

# Compiler types
FC = gfortran
CC = gcc
CXX = gcc

# Optimization level
OPT    = -O2

# Relevant flags
FFLAGS = ${OPT} 
CFLAGS = ${OPT} 
CXXFLAGS = ${OPT} 

# Name of the program
PROG  = main.x

# List of object files
OBJ = main.o

.f90.o: 
    ${FC} -c -o $@ ${FFLAGS} $<

.F90.o: 
    ${FC} -c -o $@ ${FFLAGS} $<

.c.o: 
    ${CC} -c -o $@ ${FFLAGS} $<

.cpp.o:
    ${CXX} -c -o $@ ${FFLAGS} $<

all:${PROG}

$(PROG): ${OBJ}
    $(CXX) ${FFLAGS} $(OBJ) -o ${PROG}
    mv ${PROG} ./bin/

clean:
    /bin/rm -f *.mod *.o *.x *~ ./src/*.o ./src/*~

uninstall: 
    rm -f bin/${PROG} 

renew:
    touch *

我得到的错误列表的 sn-p 是:

main.o:main.cpp:(.text.startup+0x1e): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)'
main.o:main.cpp:(.text.startup+0x1e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)'

该项目本身与计算机科学无关 - 这只是我们必须提供可交付成果的格式,所以我为让它发挥作用所付出的努力感到有点沮丧。

非常感谢大家提供的任何帮助!

【问题讨论】:

    标签: c++ unix makefile compiler-errors


    【解决方案1】:

    改变

    CXX = gcc
    

    CXX = g++
    

    原因是

    $(PROG): ${OBJ}
        $(CXX) ${FFLAGS} $(OBJ) -o ${PROG}
    

    rule 当前使用 C 编译器进行最终链接,但 C++ 对象需要一点特殊处理。基本上是 -lstdc++,您可以添加它,但最好只使用 C++ 编译器作为最终链接,特别是因为名为 CXX 的变量通常代表 C++ 编译器,而不是 C 编译器。

    仅供参考,就风格而言,最好将${...}(shell 语法)替换为$(...)(正常的Makefile 语法)。

    【讨论】:

    • 哇。如此简单的修复,现在一切正常。非常感谢您的帮助,以及我实际上可以遵循的解释!
    • 您也可以使用${CXXFLAGS} 代替FFLAGS,因为语言的选项可能不同,因此请使用CXX 进行C++ 编译。